web-dev-qa-db-fra.com

Comment exécuter des scripts après la composition de docker?

J'essaie de rendre mon processus de développement plus facile/maintenable en utilisant docker (-compose). Je ne veux pas utiliser de volumes (si c'est possible). Pourquoi import.sh n'est-il pas exécuté après avoir exécuté 'docker-compose up -d'?

J'ai les fichiers suivants:

docker-compose.yml
  mysql
  ---- import.sh
  ---- db.sql
  ---- Dockerfile

dans docker-compose.yml il y a:

version: '2'

services:
  database:
    image: mysql
    build:
      context: ./mysql/
      dockerfile: Dockerfile
    container_name: mysqltest
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: 123456

dans / mysql/Dockerfile il y a:

ADD import.sh /tmp/import.sh
ADD db.sql /tmp/db.sql
RUN /tmp/import.sh

dans / mysql/db.sql il y a:

CREATE DATABASE test1;
CREATE DATABASE test2;
CREATE DATABASE test3;
17
p0rter

Vous pouvez utiliser ENTRYPOINT ou CMD dans votre Dockerfile pour exécuter une commande au démarrage du conteneur. La différence entre eux est que ENTRYPOINT est exécuté à chaque démarrage du conteneur, tandis que CMD peut être remplacé par une option de ligne de commande. En supposant que la commande que vous souhaitez exécuter est X

docker run my-image Y

exécutera X si ENTRYPOINT X était dans le Dockerfile et Y si CMD X était dans le Dockerfile.

Cependant, il y a deux mises en garde:

  1. La commande sera exécutée à chaque démarrage du conteneur.
  2. Une fois la commande terminée, le conteneur est arrêté.

Par conséquent, une solution typique consiste à avoir un docker-entrypoint script. Il vérifie s'il est exécuté dans un nouveau conteneur qui lance son environnement et exécute ensuite le programme réel du conteneur. Jetez un œil au Dockerfile mysql officiel et point d'entrée pour vous faire une idée.

Un exemple de script de point d'entrée pourrait ressembler à ceci:

$ cat docker_entrypoint.sh                                                                                                                                          
if [ ! -f .initialized ]; then                                                                                                                                                                                    
    echo "Initializing container"                                                                                                                                                                                 
    # run initializing commands                                                                                                                                                                                   
    touch .initialized                                                                                                                                                                                            
fi                                                                                                                                                                                                                

exec "$@"

Tout d'abord, il vérifie s'il existe un fichier appelé .initialized. S'il n'y en a pas, certaines commandes sont exécutées pour initialiser l'environnement de conteneur. Après quoi touch .initialized crée .initialized en tant que fichier vide. Par conséquent, les démarrages de conteneur suivants n'exécuteront pas à nouveau la commande d'initialisation. Deuxièmement, il démarre le service réel. Faire cela avec exec remplacera le processus Shell par le processus du service. Par conséquent, docker maintiendra le conteneur en cours d'exécution jusqu'à la fin du service. "$@" contiendra la "commande conteneur/image". Ceci est défini avec CMD X dans le Dockerfile et est remplacé par la commande, comme je l'ai déjà souligné ci-dessus. En utilisant exec "$@" vous pourrez démarrer différents programmes dans le conteneur pour inspection, par ex. bash, et démarrez le service par défaut, comme spécifié dans l'instruction CMD du Dockerfile.

20
fzgregor