A few months ago, I published my first attempt at building a Docker container for the Dancer application that powers one of my web sites. It was blatantly obvious that I was learning as I was going and the Dockerfile I was using was rather out of date. I got a deluge of good advice from various people knew a lot more about this stuff than I do.
It might have looked like I had abandoned the project, but that's not the case. A few other things took a lot of my time recently, but now I'm back to look at this again.
So here's take 2 of my Dockerfile:
FROM perl:5.30.0
LABEL maintainer="dave@perlhacks.org"
EXPOSE 1701
CMD carton exec starman --port 1701 Succession/bin/app.psgi
RUN cpanm Carton Starman
COPY . /succession
RUN cd /succession && carton install --deployment
WORKDIR /succession
The first thing you'll (hopefully) notice is that it's simpler than the previous version. I've been able to remove a few instructions - there were some things that were already installed on my base image (cpanm
and a few C libraries that I was using).
Oh, and I've moved the Dockerfile into the main code repo instead of having a separate one and having to clone the real repo into it. I really don't understand why I thought that was a good idea!
I'm not going to explain it line by line like I did last time - that would be a little repetitive.
I build an image from this file using the same docker
command as I previously did (docker build -t succession .
) and then run the container from this image with this simple shell script:
docker run --name succession \
--network="host"
-e SUCC_DB_HOST \
-e SUCC_DB_NAME \
-e SUCC_DB_USER \
-e SUCC_DB_PASS \
-p 1701:1701 succession
The various SUCC_DB_*
environment variables used in the script contain the connection details for the database that the application uses. And if I have a database running and those variables set correctly, then I can get the application in a browser looking at port 1701 on localhost
.
Of course, the next thing I need is to get the database running in another container. And I now think I have a solution for that. I've created another Dockerfile called Dockerfile-db
and it contains this:
FROM mariadb/server:10.3
LABEL maintainer="dave@perlhacks.org"
COPY data/succession.dump /docker-entrypoint-initdb.d/succession.dump.sql
As you'll see, it's very simple. I've based it on an official MariaDB image and the only thing I've added is to copy a file from the Git checkout into a directory called /docker-entrypoint-initdb.d
. If the MariaDB image sees a file with the extension .sql
in that directory at run-time, then that data is loaded into the database. As it happens, my data is pretty static and I already have a dump of it in the Git repo.
I build my image with the command docker build -t succession-db -f Dockerfile-db .
and then run it with this script:
docker run --name succession-db \
-e MARIADB_ROOT_PASSWORD=sekrit \
-e MARIADB_DATABASE=$SUCC_DB_NAME \
-e MARIADB_USER=$SUCC_DB_USER \
-e MARIADB_PASSWORD=$SUCC_DB_PASS \
-p 13306:3306 -d succession-db
The MARIADB_*
environment variables are all documented on the Docker Hub page for the image. And I've remapped the port to a higher number so it doesn't clash with any DB server that might already be running on the host.
Once I've run that, I can connect to the server by running:
mysql -h127.0.0.1 -u$SUCC_DB_USER -P 13306 -p$SUCC_DB_PASS -D$SUCC_DB_NAME
And I can see all of my data in the database.
So I have one container running my app and another running my database. The next step is to get them starting up together and talking to each other. That sounds like a job for docker-compose
. And a good topic for the next article in this series.
Top comments (2)
You don't need your Dockerfile-db, it's easier to just pass set up the volume on the command line (or in docker-compose.yaml). Provided you are willing to rename your .dump to .sql...
Would yield the same result.
Excellent suggestion. Thank you; that works well.