Help With My Dockerfile

Hello everyone! I just started dabbling into docker about a few weeks ago. I am trying to create my first dockerfile and having some trouble doing so. It’s a basic ubuntu/trusty container with LAMP. For some reason I get an error when trying to connect to mysql as root during the build process. Here is my dockerfile.

From ubuntu:trusty
MAINTAINER Pepsi "maddog@gmail.com"
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y
apache2
mysql-server
php5
php-pear
php5-mysql
php5-curl
php5-gd
wget
unzip
RUN echo “ServerName localhost” >> /etc/apache2/apache2.conf
RUN a2dissite *default
RUN mkdir /var/www/html/lychee
RUN mkdir -p /var/www/html/lychee/public_html
RUN mkdir -p /var/www/html/lychee/log
RUN mkdir -p /var/www/html/lychee/backups
RUN wget -P /var/www/html/lychee/public_html https://github.com/electerious/Lychee/archive/master.zip
RUN unzip /var/www/html/lychee/public_html/master.zip -d /var/www/html/lychee/public_html/
ADD lychee.conf /etc/apache2/sites-available/lychee.conf
RUN a2ensite lychee.conf
RUN a2enmod rewrite
ENV PHP_UPLOAD_MAX_FILESIZE 10M
ENV PHP_POST_MAX_SIZE 10M
RUN service mysql start
RUN mysql -u root
RUN SET PASSWORD FOR ‘root’@‘localhost’ = PASSWORD(‘asdf1234’);
RUN flush privileges;
RUN quit;
EXPOSE 80

This is the error I am getting.

Step 17 : RUN service mysql start
—> Running in 97851367fd2e

  • Starting MySQL database server mysqld
    …done.
  • Checking for tables which need an upgrade, are corrupt or were
    not closed cleanly.
    —> 237b6d62bdd6
    Removing intermediate container 97851367fd2e
    Step 18 : RUN mysql -u root
    —> Running in a1214e92f37d
    ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’ (111)
    The command ‘/bin/sh -c mysql -u root’ returned a non-zero code: 1

You should run this as two containers, and use Docker Compose to start them both together. There are a couple of reasons to do this:

  • There is a pretty solid standard mysql container on Docker Hub already, and reusing it makes your installation simpler
  • Setting up containers is much simpler if one container only runs one process
  • If you merely need to deploy a new version of your application, you don’t force yourself to also redeploy your database
  • If you’re deploying this to production, you might want to use a hosted replicated snapshotted database setup like Amazon RDS

Some other more specific comments:

Consider fetching the zip file outside the docker build sequence, and then ADDing it (implicitly unpacking it). Or, put the Dockerfile in the same repository if you can manage it. Looking at this URL in particular, it looks like you’re trying to get the tip of the master branch of a GitHub repository, but because of the way Docker layer caching works, even if upstream has changed, Docker will generally skip over this line when you try to rebuild the container.

You should assume that commands like service, systemctl, initctl, etc. just don’t work in a Dockerfile.

If you find yourself wanting to start a process in the background, this may be a sign that you need to split into multiple containers. That’s especially true if the background process is something like a database that has a natural network interface.

This is two separate shell commands, so first this runs mysql and that runs to completion, and then it tries to run the SQL command as a shell command and fails. You might need an invocation like echo ... | mysql.

One other important note here: this password is visible to anyone who runs docker history.

Never write a password in a Dockerfile like this.

A better approach is to set the password in an environment variable that’s set when the container starts. Again, the Docker Compose YAML file is a reasonable place to set it.

Step 17 : RUN service mysql start
 ---> Running in 97851367fd2e
 * Starting MySQL database server mysqld
   ...done.
 * Checking for tables which need an upgrade, are corrupt or were
not closed cleanly.
 ---> 237b6d62bdd6
Removing intermediate container 97851367fd2e

As a corollary to the “service just doesn’t work” statement above, when you get to this point, the “removing intermediate container” line is an indication that the database service has been shut down.

As a final style point, once you finish this, each RUN command will turn into a separate Docker “layer”. That’s not intrinsically bad, though there is a relatively low limit on the number of layers in an image. Common practice is to try to flatten these down; my Dockerfiles tend to look like

RUN apt-get update \
 && env DEBIAN_FRONTEND=noninteractive \
    apt-get install -y \
      apache2 \
      ... \
 && echo "ServerName localhost" >> /etc/apache2/apache2.conf \
 && ...

dmaze I would like to thank you for the in-depth explanation you provided. I went ahead and took your advice and started a separate apache/php container from mysql.

FROM php:5.6-apache
MAINTAINER Pepsi "maddog@gmail.com"
RUN apt-get update && apt-get install -y
libfreetype6-dev
libjpeg62-turbo-dev
libmcrypt-dev
libpng12-dev
wget
nano
&& docker-php-ext-install -j$(nproc) iconv mcrypt mysqli mbstring
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/
&& docker-php-ext-install -j$(nproc) gd
COPY lychee/ /var/www/html/

Docker is awesome!

This is my final dockerfile for my php:5.6-apache container. Is there anyway to combine multiple ADD or COPY commands together instead of using ADD for each single file.

FROM php:5.6-apache
MAINTAINER Pepsi "maddog@gmail.com"
RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libmcrypt-dev \
        libpng12-dev \
		wget \
		nano \
    && docker-php-ext-install -j$(nproc) iconv mcrypt mysqli mbstring exif zip \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) gd \
	&& echo "ServerName localhost" >> /etc/apache2/apache2.conf \
	&& a2dissite *default \
	&& mkdir /var/www/html/lychee \
	&& mkdir -p /var/www/html/lychee/public_html \
	&& mkdir -p /var/www/html/lychee/log \
	&& mkdir -p /var/www/html/lychee/backups
ADD lychee.conf /etc/apache2/sites-available/
ADD phpinfo.php /var/www/html/lychee/public_html/
RUN a2ensite lychee.conf \
    && a2enmod rewrite
COPY lychee/ /var/www/html/lychee/public_html/