22 November 2014

At the moment there is a great hype about “docker”, even if the technique isn’t new. So what’s so great about it?

I think it got popular, because it’s very easy to build system-containers with it. There is also a repository where you find ready to use environments for many use cases. With a few commands, you can have an isolated system with all the configs you need. That’s very nice. Compared to virtual machines, those containers need a minimum of resources because they share the resources with their host-machine and don’t run their own kernel. And they don’t need to boot, they just run when they are started. Docker implemented some kind of scripts called “Dockerfiles”. Those are recipies of how images should be configured, customized and build.

When I first heard about docker I was just thinking on developers. Now I realized how useful this tool could be for administrators too. You can use one server and serve every customer his own “linux+apache2+mysql”-system, instead of virtual hosting or chroot-ing.

In this article i want to describe how to create a “Debian Wheezy”-Image using “debootstrap”. This debianwheezy-image will be the base for our “dockerfile”. The dockerfile itself will create another image called “hoti/drupal-dev”. In this dockerfile we will pre-install a ssh-server,mysql-server, apache2-server, php5, drush and drupal.

Download a Debian Wheezy Bootstrap:

debootstrap wheezy wheezy

Our output looks like this:

I: Configuring ifupdown...
I: Configuring kmod...
I: Configuring libapt-pkg4.12:amd64...
I: Configuring libept1.4.12...
I: Configuring libapt-inst1.5:amd64...
I: Configuring libreadline6:amd64...
I: Configuring logrotate...
I: Configuring libboost-iostreams1.49.0...
I: Configuring groff-base...
I: Configuring gnupg...
I: Configuring libsigc++-2.0-0c2a:amd64...
I: Configuring libgnutls26:amd64...
I: Configuring apt-utils...
I: Configuring udev...
I: Configuring iptables...
I: Configuring man-db...
I: Configuring apt...
I: Configuring wget...
I: Configuring libcwidget3...
I: Configuring aptitude...
I: Configuring tasksel...
I: Configuring tasksel-data...
I: Base system installed successfully.

Now create a docker-image:

tar -C wheezy/ -c . | docker import - debianwheezy

And check out that it was created successfully:

docker images -a
debianwheezy latest f5c9b4660eee 18 seconds ago 218.4 MB

Lets delete the bootstrap-files:

rm -r debianwheezy

Now we create a container out of our image and install the worlds best editor into it:

docker run -it debianwheezy /bin/bash
root@5c0a2b5468c1:/# apt-get update
Hit wheezy Release.gpg
Hit wheezy Release
Hit wheezy/main amd64 Packages
Get:1 wheezy/main Translation-en [3846 kB]
Fetched 3846 kB in 5s (668 kB/s)
Reading package lists... Done
root@5c0a2b5468c1:/# apt-get install vim
Reading package lists... Done
Building dependency tree... Done
The following extra packages will be installed:
  libgpm2 vim-runtime
Suggested packages:
  gpm ctags vim-doc vim-scripts
The following NEW packages will be installed:
  libgpm2 vim vim-runtime
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 5484 kB of archives.
After this operation, 24.9 MB of additional disk space will be used.
Do you want to continue [Y/n]? y
Get:1 wheezy/main libgpm2 amd64 1.20.4-6 [35.8 kB]
Get:2 wheezy/main vim-runtime all 2:7.3.547-7 [4607 kB]
Get:3 wheezy/main vim amd64 2:7.3.547-7 [841 kB]
Fetched 5484 kB in 7s (711 kB/s)
Selecting previously unselected package libgpm2:amd64.
(Reading database ... 9308 files and directories currently installed.)
Unpacking libgpm2:amd64 (from .../libgpm2_1.20.4-6_amd64.deb) ...
Selecting previously unselected package vim-runtime.
Unpacking vim-runtime (from .../vim-runtime_2%3a7.3.547-7_all.deb) ...
Adding 'diversion of /usr/share/vim/vim73/doc/help.txt to /usr/share/vim/vim73/doc/help.txt.vim-tiny by vim-runtime'
Adding 'diversion of /usr/share/vim/vim73/doc/tags to /usr/share/vim/vim73/doc/tags.vim-tiny by vim-runtime'
Selecting previously unselected package vim.
Unpacking vim (from .../vim_2%3a7.3.547-7_amd64.deb) ...
Processing triggers for man-db ...
Setting up libgpm2:amd64 (1.20.4-6) ...
Setting up vim-runtime (2:7.3.547-7) ...
Processing /usr/share/vim/addons/doc
Setting up vim (2:7.3.547-7) ...
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vim (vim) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vimdiff (vimdiff) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/rvim (rvim) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/rview (rview) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vi (vi) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/view (view) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/ex (ex) in auto mode
root@5c0a2b5468c1:/# exit

With “exit” we stopped the container and returned back to our system. Now let’s check the state of our container:

docker ps -a
5c0a2b5468c1 debianwheezy:latest "/bin/bash" 3 minutes ago Exited (0) 45 seconds ago clever_almeida

Now let’s commit our changes into our debianwheezy image so that we have a debianwheezy image with vim pre-installed:

docker commit -m "vim installed" 5c0a2b5468c1 debianwheezy:latest

We can remove our container and create a new one to check if vim is installed:

docker rm 5c0a2b5468c1

docker run -it debianwheezy:latest /bin/bash
root@54bfa48a9ac0:/# apt-get install vim
Reading package lists... Done
Building dependency tree
Reading state information... Done
vim is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

Since this worked well, we can now stop and remove this container:

docker stop 54bfa48a9ac0
docker rm 54bfa48a9ac0

Finally it’s time for our dockerfile(i borrowed the file from

# Simple dockerfile for an ssh + server.
# Source:
# Hoti
# --

# From this base-image / starting-point
FROM debianwheezy

# Authorship

# Update apt
RUN DEBIAN_FRONTEND=noninteractive apt-get update -q -q
RUN DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes --force-yes

# Install utitiles
RUN DEBIAN_FRONTEND=noninteractive apt-get install curl git less sudo screen --yes --force-yes

# Install runit
RUN DEBIAN_FRONTEND=noninteractive apt-get install runit --yes --force-yes

# Install SSH
RUN DEBIAN_FRONTEND=noninteractive apt-get install openssh-server openssh-client --yes --force-yes

# Install MySQL
RUN DEBIAN_FRONTEND=noninteractive apt-get install mysql-server --yes --force-yes

# Install Apache2 + php5
RUN DEBIAN_FRONTEND=noninteractive apt-get install apache2 php5 php5-cli php5-mysql php5-gd --yes --force-yes

# Setup a root password; simple enough to remember, but hard enough that
# it won't be cracked immediately. (ha!)
RUN echo "root:toor" | chpasswd

# Expose the SSH port

# Expose the Apache2 port

# Now make sure that runit will launch SSHD, via runit.
# NOTE: Remember runit will launch /etc/service/sshd/run
RUN mkdir /etc/service/sshd
RUN /bin/echo -e '#!/bin/sh' > /etc/service/sshd/run
RUN /bin/echo -e 'exec /usr/sbin/sshd -D' >> /etc/service/sshd/run

RUN mkdir /etc/service/mysqld
RUN /bin/echo -e '#!/bin/sh' > /etc/service/mysqld/run
RUN /bin/echo -e 'exec mysqld_safe &' >> /etc/service/mysqld/run

RUN mkdir /etc/service/apache2
RUN /bin/echo -e '#!/bin/sh' > /etc/service/apache2/run
RUN /bin/echo -e 'exec apachectl start' >> /etc/service/apache2/run

# Make sure our run-script is executable.
RUN chown root.root /etc/service/sshd/run
RUN chmod 755 /etc/service/sshd/run

RUN chown root.root /etc/service/mysqld/run
RUN chmod 755 /etc/service/mysqld/run

RUN chown root.root /etc/service/apache2/run
RUN chmod 755 /etc/service/apache2/run

# Install composer + drush
RUN curl -sS | php
RUN mv composer.phar /usr/local/bin/composer
RUN chown root.root /usr/local/bin/composer
RUN chmod 755 /usr/local/bin/composer
RUN composer global require drush/drush:dev-master
RUN ln -s /root/.composer/vendor/drush/drush/drush /usr/local/bin/drush
RUN ln -s /root/.composer/vendor/drush/drush/ /etc/bash_completion.d/
RUN mkdir /etc/drush
RUN mkdir /var/www/drupal
RUN echo '> /etc/drush/drushrc.php
RUN echo '$options['r'] = '/var/www/drupal';' >> /etc/drush/drushrc.php
RUN cd /var/www && git clone --branch 7.x
RUN cd /var/www/drupal/sites/default && mkdir /var/www/drupal/sites/default/files && cp default.settings.php settings.php
# RUN mysqladmin -uroot create drupal
RUN chown www-data /var/www/drupal/sites/default/files
RUN chown www-data /var/www/drupal/sites/default/settings.php
RUN a2enmod rewrite

# Finally launch runit.
ENTRYPOINT ["/usr/sbin/runsvdir-start"]

Download the Dockerfile here.

Build the image using the Dockerfile:

docker build -t=hoti/drupal-dev - < Dockerfile.runit

.. And create an container-instance:

docker run -d -p 1122:22 -p 1180:80 hoti/drupal-dev

Now we can connect via ssh:

ssh root@localhost -p 1122

..Or using a browser:

[ Linux  Sysadmin  Docker  Drupal  ]
Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 Unported License.

Copyright 2015-present Hoti