Install mysql in dockerfile?

Vladimir Fejsov picture Vladimir Fejsov · Apr 2, 2015 · Viewed 15k times · Source

I want to write simple python application and put in docker conteiner with dockerfile. My dockerfile is:

FROM ubuntu:saucy

# Install required packages
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install python
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install mysql-server python-mysqldb

# Add our python app code to the image
RUN mkdir -p /app
ADD . /app
WORKDIR /app

# Set the default command to execute
CMD ["python", "main.py"]

In my python application I only want to connect to the database. main.py look something like this:

import MySQLdb as db

connection = db.connect(
                host='localhost',
                port=3306,
                user='root',
                passwd='password',
            )

When I built docker image with:

docker build -t myapp .

and run docker image with:

docker run -i myapp

I got error:

_mysql_exceptions.OperationalError: (2002, "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)")

What is the problem?

Answer

Adrian Mouat picture Adrian Mouat · Apr 2, 2015

The problem is that you've never started the database - you need to explicitly start services in most Docker images. But if you want to run two processes in Docker (the DB and your python program), things get a little more complex. You either have to use a process manager like supervisor, or be a bit cleverer in your start-up script.

To see what I mean, create the following script, and call it cmd.sh:

#!/bin/bash

mysqld &
python main.py

Add it to the Dockerfile:

FROM ubuntu:saucy

# Install required packages
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install python
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install mysql-server python-mysqldb

# Add our python app code to the image
RUN mkdir -p /app
ADD . /app
WORKDIR /app

# Set the default command to execute
COPY cmd.sh /cmd.sh
RUN chmod +x /cmd.sh
CMD cmd.sh

Now build and try again. (Apologies if this doesn't work, it's off the top of my head and I haven't tested it).

Note that this is not a good solution; mysql will not be getting signals proxied to it, so probably won't shutdown properly when the container stops. You could fix this by using a process manager like supervisor, but the easiest and best solution is to use separate containers. You can find stock containers for mysql and also for python, which would save you a lot of trouble. To do this:

  1. Take the mysql installation stuff out of the Dockerfile
  2. Change localhost in your python code to mysql or whatever you want to call your MySQL container.
  3. Start a MySQL container with something like docker run -d --name mysql mysql
  4. Start your container and link to the mysql container e.g: docker run myapp --link mysql:mysql