After having played a little bit with Docker, it's time to try something more serious: I'll try to set up a Drupal web server, relying on following containers:
In order to have data-only containers with minimal disk space overhead, I'll build them on a Busybox image. But this will require additional containers, used for initialization (there could be some other solutions but, being a Docker beginner, I didn't find a good one).
The working directory I'll use, on my Linux development machine, is /root/dockerTests/. [I upgraded my Mac to Yosemite, and it seems that this had a bad side effect of docker2boot, so I switched back to Linux, before spending some time on cleaning Docker configuration on the Mac.]
So, let's go!
#DOCKER-VERSION 1.3.0
# We'll rely on Ubuntu 14.04 LTS.
FROM ubuntu:14.04
# Install required software.
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
apache2 \
libapache2-mod-auth-mysql \
libapache2-mod-php5 \
nano \
php5 \
php5-gd \
php5-mcrypt \
php5-mysql
# Activate Drupal web site.
ADD drupal.conf /etc/apache2/sites-available/
RUN a2dissite 000-default
RUN a2ensite drupal
# Expose port 80 to the host machine
EXPOSE 80
ENTRYPOINT ["/usr/sbin/apache2ctl"]
CMD ["-D", "FOREGROUND"]<VirtualHost *:80>
DocumentRoot /var/www/drupal/
LogLevel warn
ErrorLog /dev/stdout
CustomLog /dev/stdout combined
</VirtualHost>docker build -t pascalbod/apache2:v1 .
#DOCKER-VERSION 1.3.0 # Minimal image. FROM busybox:ubuntu-14.04 # Declare volume for web site directory. VOLUME /var/www/drupal CMD ["true"]
docker build -t pascalbod/drupalweb:v1 .
docker run -d --name drupalweb pascalbod/drupalweb:v1
#DOCKER-VERSION 1.3.0
# We'll rely on Ubuntu 14.04 LTS.
FROM ubuntu:14.04
# Install required software.
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
wget
# Script used at run time to initialize Drupal web site container.
ADD run.sh /run.sh
RUN chmod u+x /run.sh
CMD ["/run.sh"]#!/bin/bash
# Download Drupal
echo "=> Downloading Drupal."
wget http://ftp.drupal.org/files/projects/drupal-7.33.tar.gz
tar -xvzf drupal-7.33.tar.gz
rm drupal-7.33.tar.gz
# Move files to intended location
echo "=> Moving files."
cd drupal-7.33/ mv * .htaccess .gitignore /var/www/drupal/.
cd ..
rmdir drupal-7.33/
# Prepare settings.php and file permissions
echo "=> Preparing settings.php and file permissions."
cd /var/www/drupal/ cp sites/default/default.settings.php sites/default/settings.php chmod a+w sites/default/settings.php chmod a+w sites/default
echo "=> Done."
docker build -t pascalbod/drupalwebinit:v1 .
docker run -d --volumes-from drupalweb pascalbod/drupalwebinit:v1
#DOCKER-VERSION 1.3.0 # Minimal image. FROM busybox:ubuntu-14.04 # Declare volume for database directory. VOLUME /var/lib/mysql CMD ["true"]
docker build -t pascalbod/drupaldb:v1 .
#DOCKER-VERSION 1.3.0
# We'll rely on Ubuntu 14.04 LTS.
FROM ubuntu:14.04
# Install required software.
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
mysql-client \
mysql-server
# Set up MySQL configuration so that we can access it from outside.
ADD my.cnf /etc/mysql/conf.d/my.cnf
# Add script that initializes MySQL data directory.
ADD run.sh /run.sh
RUN chmod a+x /run.sh
# Expose MySQL port to the host machine.
EXPOSE 3306[mysqld] bind-address=0.0.0.0
#!/bin/bash
if [ ! -d /var/lib/mysql/mysql ]; then
# Setup MySQL data directory.
echo "=> Creating MySQL data directory."
mysql_install_db --datadir=/var/lib/mysql
fi
echo "=> Running MySQL Server."
exec mysqld_safe --datadir=/var/lib/mysqldocker build -t pascalbod/mysqlinit:v1 .
docker run -d --name drupaldb pascalbod/drupaldb:v1
#DOCKER-VERSION 1.3.0
# We'll rely on Ubuntu 14.04 LTS.
FROM ubuntu:14.04
# Install required software.
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
mysql-client \
mysql-server
# Script used at run time to initialize Drupal database container.
ADD run.sh /run.sh
RUN chmod u+x /run.sh
CMD ["/run.sh"]#!/bin/bash
echo "=> Initializing MySQL data."
mysql_install_db
echo "=> Starting MySQL server."
/usr/bin/mysqld_safe &
echo "=> Waiting for MySQL server."
while (true); do
echo " waiting for 3 s..."
sleep 3s
mysql -uroot -e "status" > /dev/null 2>&1 && break
done
echo "=> Setting MySQL root password."
PASS='pw0drupal0'
mysql -uroot -e "update mysql.user set Password=password('$PASS') where user = 'root';"
echo "=> Creating drupal database and user."
mysql -uroot -e "CREATE DATABASE drupal CHARACTER SET utf8 COLLATE utf8_general_ci;"
PASS='pw1drupal1'
mysql -uroot -e "CREATE USER 'drupal'@'%' IDENTIFIED BY '$PASS';"
mysql -uroot -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, \
CREATE TEMPORARY TABLES ON drupal.* TO 'drupal'@'%';"
echo "=> Done." docker build -t pascalbod/drupaldbinit:v1 .
docker run -d --volumes-from drupaldb pascalbod/drupaldbinit:v1
#DOCKER-VERSION 1.3.0
# We'll rely on Ubuntu 14.04 LTS.
FROM ubuntu:14.04
# Install required software.
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
mysql-client \
mysql-server
# Set up MySQL configuration so that we can access it from outside.
ADD my.cnf /etc/mysql/conf.d/my.cnf
# Expose MySQL port to the host machine.
EXPOSE 3306
ENTRYPOINT ["mysqld_safe"][mysqld] bind-address=0.0.0.0
docker build -t pascalbod/mysql:v1 .
docker run -d --volumes-from drupaldb --name db pascalbod/mysql:v1
At this stage, we have a running Drupal web site container, a running Drupal database container and a running MySQL container. Now let's start Apache container:
docker run -d -p 23001:80 --volumes-from drupalweb --link db:db pascalbod/apache2:v1
Now, Drupal configuration web page is available at <myHost>:23001 (I chose a random port, for configuration duration).
When asked for database information, click on ADVANCED OPTIONS, and set database host to db, the link alias we provided to above command.
A few additional adjustements should be performed: some file ownership settings, addition of some Drupal modules, etc. One way to do this is to use the exec command on target container:
docker exec -i -t <containerId> bash
This creates a new bash session in the container, which I use to end Drupal configuration.
I'm quite sure the way I used Docker to set up my Drupal configuration is not an optimal one. I tried to use one container per service, and one container per type of persistant data. This design choice seems to comply with some Docker container patterns. But the way I implemented it is quite complex. It wasn't so easy to set up. What's more, I wonder whether that's the best answer to my needs. I'll spend some more time using Docker over the next few months, and I'll discover a lot more than I know today
. This should allow me to optimize this complex set up... As Chinese people say: 熟能生巧 (skill comes from practice).
05-Jan-2015 - Update: see this article for the Drupal configuration I finally chose, for a live Drupal site.