How to get MYSQL to start on docker run and creating mysql users in Dockerfile

Viewed 985

I have a Dockerfile (seen below). The image generates without issue. With all the items installed that I would expect. However the MYSQL users and the DB that I'm "restoring" don't appear to be there. I have to exec into the instance and manually start the mysql service again, add the users, create the DB and then run the gunzip line again. I'd like this to happen when the image generates then I'd like mysql to start on the run command. Any help is appreciated.

UPDATED

So I've learned that the original version I had where I was trying to create mysql users, dbs and restoring a db doesn't work. So in research it looks like I'm supposed to put .sh or .sql files etc in /docker-entrypoint-initdb.d/ and that they should run the first time I run the container. However, that appears to not work for me so obviously I'm missing something. I'm including my .sh file below as well.

#Download base image ubuntu 16.04
FROM ubuntu:16.04

# Let the conatiner know that there is no tty
ENV DEBIAN_FRONTEND noninteractive

# Update Software repository
RUN apt-get update

# Add Language Packs
RUN apt-get install -y language-pack-en-base

# Set the locale
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    locale-gen
ENV LANG en_US.UTF-8  
ENV LANGUAGE en_US:en  
ENV LC_ALL en_US.UTF-8 

# Add Current PHP Repository
RUN apt-get install software-properties-common -y
RUN add-apt-repository -y ppa:ondrej/php
RUN add-apt-repository -y ppa:ondrej/mysql-5.6
RUN apt-get update

# Basic Requirements
RUN apt-get -y install pwgen python-setuptools curl git nano sudo unzip openssh-server openssl vim htop
RUN apt-get -y install php7.4-fpm php7.4-common php7.4-mysql php7.4-xml php7.4-xmlrpc php7.4-curl php7.4-gd php7.4-imagick php7.4-cli php7.4-dev php7.4-imap php7.4-mbstring php7.4-soap php7.4-zip php7.4-bcmath php7.4-memcache php7.4-mysql
RUN apt-get -y install mysql-server-5.6 mysql-client-5.6 nginx
RUN apt-get install -y supervisor && \
    rm -rf /var/lib/apt/lists/*

# mysql config
RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/explicit_defaults_for_timestamp = true\nbind-address = 0.0.0.0/" /etc/mysql/mysql.conf.d/mysqld.cnf    

#Define the ENV variable
ENV nginx_vhost /etc/nginx/sites-available/default
ENV php_conf /etc/php/7.4/fpm/php.ini
ENV nginx_conf /etc/nginx/nginx.conf
ENV supervisor_conf /etc/supervisor/supervisord.conf

# Enable php-fpm on nginx virtualhost configuration
COPY default ${nginx_vhost}
RUN sed -i -e 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' ${php_conf} && \
    echo "\ndaemon off;" >> ${nginx_conf}

#Copy supervisor configuration
COPY supervisord.conf ${supervisor_conf}    

RUN mkdir -p /run/php && \
    chown -R www-data:www-data /var/www/html && \
    chown -R www-data:www-data /run/php

# Volume configuration
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html", "/var/lib/mysql"]

# ROOT PASSWORD
ENV MYSQL_ROOT_PASSWORD=root

ENV MYSQL_DATABASE=tsc_sandbox
ENV MYSQL_USER=tsc_user
ENV MYSQL_PASSWORD=tsc_user

# Copy Conf File Over
COPY web-application.conf /etc/nginx/conf.d/web-application.conf

# Handle SSL Certs
RUN mkdir /etc/nginx/ssl
COPY web-application.crt /etc/nginx/ssl/web-application.crt
COPY web-application.key /etc/nginx/ssl/web-application.key

# Setup Mysql DB
COPY init-file.sh /docker-entrypoint-initdb.d/init-file.sh
RUN chmod +x /docker-entrypoint-initdb.d/init-file.sh

# Configure Services and Port
COPY start.sh /start.sh
CMD ["./start.sh"]

COPY tsc-20200310.sql.gz /tsc-20200310.sql.gz
RUN chmod +x /tsc-20200310.sql.gz

# Network Ports
EXPOSE 80 443 3306 22

The command I'm using to run the container is:

docker run -detach -v ~/hosts/web-application:/var/www/html -p 80:80 -p 443:443 -p 3306:3306 -p 22:22 --name container_1 container_image

The command I'm using to build the image is:

docker build -t container_image .

init-file.sh

#!/bin/bash

/etc/init.d/mysql start

mysql -u root -e "CREATE USER 'tsc_user'@'%' IDENTIFIED BY 'tsc_user';"
mysql -u root -e "CREATE USER 'the_master'@'%' IDENTIFIED BY 'the_master';"
mysql -u root -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, SHOW VIEW ON *.* TO 'tsc_user'@'%';"
mysql -u root -e "GRANT SELECT ON *.* TO the_master'@'%';"
mysql -u root -e "CREATE DATABASE tsc_sandbox;"

gunzip < /tsc-20200310.sql.gz | mysql -u root tsc_sandbox;

as a note I can obviously exec into the container afterwards and run that shell file and everything works as intended. Just hoping to get it to happen when I use the docker run command.

1 Answers

I wanted to at least update with a partial answer. I haven't yet figured out how to do everything I wanted but I've at least gotten further. Since I was already using supervisor, I added the starting of mysql to it. Below you can see my Dockerfile, .sh files, default and supervisord.conf file.

Dockerfile

#Download base image ubuntu 16.04
FROM ubuntu:16.04

# Let the conatiner know that there is no tty
ENV DEBIAN_FRONTEND noninteractive

# Update Software repository
RUN apt-get update

# Add Language Packs
RUN apt-get install -y language-pack-en-base

# Set the locale
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    locale-gen
ENV LANG en_US.UTF-8  
ENV LANGUAGE en_US:en  
ENV LC_ALL en_US.UTF-8 

# Add Current PHP Repository
RUN apt-get install software-properties-common -y
RUN add-apt-repository -y ppa:ondrej/php
RUN add-apt-repository -y ppa:ondrej/mysql-5.6
RUN apt-get update

# Basic Requirements
RUN apt-get -y install pwgen python-setuptools curl git nano sudo unzip openssh-server openssl vim htop
RUN apt-get -y install php7.4-fpm php7.4-common php7.4-mysql php7.4-xml php7.4-xmlrpc php7.4-curl php7.4-gd php7.4-imagick php7.4-cli php7.4-dev php7.4-imap php7.4-mbstring php7.4-soap php7.4-zip php7.4-bcmath php7.4-memcache php7.4-mysql
RUN apt-get -y install mysql-server-5.6 mysql-client-5.6 nginx
RUN apt-get install -y supervisor && \
    rm -rf /var/lib/apt/lists/*

# mysql config
RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/explicit_defaults_for_timestamp = true\nbind-address = 0.0.0.0/" /etc/mysql/mysql.conf.d/mysqld.cnf    

#Define the ENV variable
ENV nginx_vhost /etc/nginx/sites-available/default
ENV php_conf /etc/php/7.4/fpm/php.ini
ENV nginx_conf /etc/nginx/nginx.conf
ENV supervisor_conf /etc/supervisor/supervisord.conf

# Enable php-fpm on nginx virtualhost configuration
COPY default ${nginx_vhost}
RUN sed -i -e 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' ${php_conf} && \
    echo "\ndaemon off;" >> ${nginx_conf}

#Copy supervisor configuration
COPY supervisord.conf ${supervisor_conf}    

RUN mkdir -p /run/php && \
    chown -R www-data:www-data /var/www/html && \
    chown -R www-data:www-data /run/php

# Volume configuration
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html", "/var/lib/mysql"]

# ROOT PASSWORD
ENV MYSQL_ROOT_PASSWORD=root

ENV MYSQL_DATABASE=tsc_sandbox
ENV MYSQL_USER=tsc_user
ENV MYSQL_PASSWORD=tsc_user

# Setup Mysql DB
COPY db-init.sh /docker-entrypoint-initdb.d/db-init.sh
RUN chmod +x /docker-entrypoint-initdb.d/db-init.sh
RUN /etc/init.d/mysql start

# Configure Services and Port
COPY start.sh /start.sh
CMD ["./start.sh"]

COPY tsc_sandbox.sql.gz /tsc_sandbox.sql.gz
RUN chmod +x /tsc_sandbox.sql.gz

# Network Ports
EXPOSE 80 443 3306 22 11211 3000 9000 10137 20080

start.sh

#!/bin/sh

/usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf

db-init.sh

#!/bin/bash

mysql -u root -e "CREATE USER 'tsc_user'@'%' IDENTIFIED BY 'tsc_user';"
mysql -u root -e "CREATE USER 'memaster'@'%' IDENTIFIED BY 'memaster';"
mysql -u root -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, SHOW VIEW ON *.* TO 'tsc_user'@'%';"
mysql -u root -e "GRANT SELECT ON *.* TO 'memaster'@'%';"
mysql -u root -e "CREATE DATABASE tsc_sandbox;"

gunzip < /tsc_sandbox.sql.gz | mysql -u root tsc_sandbox;

default

server {
    listen 80;
    listen [::]:80 ipv6only=on default_server;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny all;
    #}
}

supervisord.conf

[unix_http_server]
file=/dev/shm/supervisor.sock   ; (the path to the socket file)

[supervisord]
logfile=/var/log/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB        ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10           ; (num of main logfile rotation backups;default 10)
loglevel=info                ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false               ; (start in foreground if true;default false)
minfds=1024                  ; (min. avail startup file descriptors;default 1024)
minprocs=200                 ; (min. avail process descriptors;default 200)
user=root             ;

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///dev/shm/supervisor.sock ; use a unix:// URL  for a unix socket

; The [include] section can just contain the "files" setting.  This
; setting can list multiple files (separated by whitespace or
; newlines).  It can also contain wildcards.  The filenames are
; interpreted as relative to this file.  Included files *cannot*
; include files themselves.

[include]
files = /etc/supervisor/conf.d/*.conf


[program:php-fpm7.4]
command=/usr/sbin/php-fpm7.4 -F
numprocs=1
autostart=true
autorestart=true

[program:nginx]
command=/usr/sbin/nginx
numprocs=1
autostart=true
autorestart=true

[program:mysql]
command=/usr/bin/pidproxy /var/run/mysqld/mysqld.pid /usr/sbin/mysqld
autorestart=true

Ideally I would be able to have the db-init.sh script run the first time the docker is ran without the need to exec into it and run it. Outside of that, this works pretty well thus far.

Related