Docker, Part I
Having opted for a project which entails having one Dockerised application run another, getting to grips with Docker an inevitability.
The first item on the agenda was to get something resembling a production environment running inside a container. Instinctively I opted for doing with within a single container. I started by basing the container/image on Alpine Linux a popular light-weight distribution which uses Busybox.
While we had originally proposed to use MySQL for our production database, a little research on the topic showed that the Django developers recommend PostgreSQL. (They express far fewer caveats about it at any rate).
FROM alpine:3 # apache runs on port 80 by default EXPOSE 80 # install system packages RUN apk add --no-cache python3 py3-pip postgresql15 apache2 apache2-ctl \ apache2-mod-wsgi py3-psycopg2
Using Alpine also allows us to take advantage of its convenient package manager apk. Here where thing got a little sticky however as apk installs an older version of Django - 3.6 - that the 4.1 we have been using for development.
Installing pip and using it to install Django solves this problem.
# installing django from pip means we get a more recent version RUN pip install django django-bootstrap5
Having two services in the same container complicated the init script as Docker's CMD directive expects the command to run and not return. A simple init script solves the problem
#!/bin/sh
echo Starting Up...
# start apache
apachectl start
# start postgres database
mkdir -p /run/postgresql
chown postgres:postgres /run/postgresql
su postgres -c "/usr/bin/pg_ctl -w -l $POSTGRES_LOG start"
# shutdown func
stop() {
echo Shutting Down...
apachectl stop
su postgres -c "/usr/bin/pg_ctl -w stop"
exit 0
}
trap stop EXIT
sleep infinity ∓
wait
This script has a couple of advantages. First, it allows for the orderly wind down of Postgres and Apache. Second, if for some reason either or both services don't start you can still open a shell and try to diagnose problems, restart etc... just as you would on an actual machine.
An interesting side note on Busybox's implementation of sleep infinity. It calls the sleep system call for INT_MAX seconds within an indefinite loop. Given that INT_MAX seconds would last 68 years, they probably needn't have bothered.
Comments
Post a Comment