Docker - how to alter my Docker Compose file to automate a bash script for the MySQL container?

1k Views Asked by At

I have the following setup Docker Composer setup and want to run a shell script to automate tasks like importing the DB into the MySQL database.

# Adopt version 2 syntax:
version: '2'

volumes:
    database_data:
        driver: local

services:
###########################
# Setup the Nginx container
###########################
nginx:
    image: nginx:latest
    ports:
        - 8080:80
    volumes:
        - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    volumes_from:
        - php

###########################
# Setup the PHP container
###########################
php:
    build: ./docker/php/
    expose:
        - 9000
    volumes:
        - .:/var/www

###########################
# Setup the Database (MySQL) container
###########################
mysql:
    image: mysql:latest
    expose:
        - 3306
    volumes:
        - database_data:/var/lib/mysql
    environment:
        MYSQL_ROOT_PASSWORD: secret
        MYSQL_DATABASE: project
        MYSQL_USER: project
        MYSQL_PASSWORD: project
2

There are 2 best solutions below

0
On

You can keep using a the original image: load your setup script into the container as a Config (using the long-form definition so you can set the execute permission), and then override the Entrypoint to run your script (which should probably run the original entrypoint script once it finishes). So something like:

mysql:
image: mysql:latest
expose:
    - 3306
volumes:
    - database_data:/var/lib/mysql
environment:
    MYSQL_ROOT_PASSWORD: secret
    MYSQL_DATABASE: project
    MYSQL_USER: project
    MYSQL_PASSWORD: project
configs:
    - source: ./OverrideScript.sh
    target: /OverrideScript.sh
    #0777 will work too, but you can't write to it either way
    mode: 0555
entrypoint: /OverrideScript.sh

The other answers are right that the "Proper" way would be to make your own image. But TBH if your override script is relatively small and lightweight, the workaround isn't so bad, and it gets you out of having to rebuild your custom image every time MySQL releases a new image.

1
On

Best solution is to create a custom Dockerfile ,which extends mysql and add a custom shell script, which does what you want. For example:

start.sh

#!/bin/sh

mysqld
mysql -u project -ppropject project < /path/to/backup.sql

Don't forget to add your backup.sql either to your Dockerfile or docker-compose.yml

Now, Dockerfile:

FROM mysql:latest

COPY start.sh /tmp/start.sh
COPY backup.sql /path/to/backup.sql

CMD ["/tmp/start.sh"]

If you change your backup.sql frequently, it makes no sense to add it to Dockerfile. Instead, put it under volumes in docker-compose.yml:

mysql:
    build: .
    expose:
        - 3306
    volumes:
        - ./backup.sql:/path/to/backup.sql
        - database_data:/var/lib/mysql
    environment:
        MYSQL_ROOT_PASSWORD: secret
        MYSQL_DATABASE: project
        MYSQL_USER: project
        MYSQL_PASSWORD: project