Install and run a web server in a docker container

Last week we created a docker image with a Debian base installation which will serve us as the starting point in today’s article. In the next sections you will learn in some sort of hard way to provision your docker-based guest system. At the end we will see a web server running in its sandboxed environment.

Import your base image

If you uploaded the image to your upstream server run …

$ docker import http://your-server.com/wheezy.tar
120746ec5e2e5e74bb5b8e8c5a0d4719206522cc63b724f3722d11e93f397b16

… or if you prefer to import the local archive execute one of the three commands …

$ cat wheezy.tar | docker import -
0d471920120746ec5e2e5e74ba6522cc63b724f3722d11e93f397b16b5b8e8c5

… and now the image will be located in /var/lib/docker/graph.

The returned ID is your image ID to be used if you want to delete the image later. We’ll deal with another ID type later, the container IDs. To ease your life give your image a tag name as follows.

$ cat wheezy.tar | docker import - debian:wheezy
456574fc26beb18af9e19b95793b98a014a2ff2f52c73e1a980a93cd808d5a32

Docker will show you a list of all imported images with the import command. As we see below our image has been successfully imported and is awaiting for your next move.

$ docker images
REPOSITORY       TAG              IMAGE ID         CREATED            VIRTUAL SIZE
debian           wheezy           456574fc26be     17 seconds ago     84.11 MB

Install a web server

If you created your own bridge make sure you assigned an IP range to your bridge …

$ ip addr add 10.0.31.10/16 dev docker0

… or you’ll get something like the following error if you’re trying to start a container.

2014/09/03 20:39:51 Error response from daemon: Cannot start container 9334a2af5bc577008c8d3294cf2ed1d007e53e222bfdfe2a3158aa215e4e4a7e: no available ip addresses on network

At this time let’s run a shell and thus change to the chroot environment.

$ docker run -i -t debian:wheezy /bin/bash

The general scheme to run an application in a docker container is

docker run -i -t <image> <binary> 

Option -i means that you run the shell interactively so that as soon as you exit from the container’s shell the container is stopped. Otherwise you would exit but the container would still run. By specifying option -t you advice docker to allocate a pseudo-tty, or in other words you will see a prompt then.

Being inside the container install apache.

root@dbe70278af6a:/# apache install apache2

Don’t execute exit to quit the interactive shell because the container process will be terminated without saving the state so the web server would be gone afterwards.

Instead type CTRL+P followed by CTRL+Q. This will bring you out of the shell without killing the process.

In order to attach to the process again find out your container ID …

$ docker ps
CONTAINER ID    IMAGE           COMMAND      CREATED              STATUS              PORTS    NAMES
dbe70278af6a    debian/wheezy   /bin/bash    About a minute ago   Up About a minute            thirsty_blackwell

… and execute

$ docker attach --sig-proxy=false dbe70278af6a

By specifying --sig-proxy all received signals are proxied to the process even in non-tty mode, however, SIGCHLD is not.

Note: the CTRL+P/CTRL+Q trick works only if a container is run in tty mode.

Create a new image

Once we have the container ID we can commit our changes to a new image.

$ docker commit dbe70278af6a slopjong/apache

To reduce data corruption the container and its processes will be paused during the commit. In the case you’d need to commit a running container you can use the -p option.

$ docker commit -p false dbe70278af6a slopjong/apache

To make sure everything went fine so far we should check the list of available images again.

$ docker images
REPOSITORY       TAG              IMAGE ID         CREATED            VIRTUAL SIZE
slopjong/apache  latest           55cf2176b4f2     29 minutes ago     388.8 MB
debian           wheezy           456574fc26be     17 seconds ago     84.11 MB

As sharing is caring you can easily export your image using the save command.

$ docker save -o wheezy-apache.tar 55cf2176b4f2

Start the web server

Starting the container with apache is dead simple. In detached mode (option -d) run apache2ctl as follows.

docker run -d -p 9999:80 slopjong/apache /usr/sbin/apache2ctl -D FOREGROUND

With this command you will forward the port 9999 from your host to port 80 of your container. This means that you point your browser to http://localhost:9999 to access the websites hosted in your docker container.

Next week …

… we will see the basic docker commands and how we can assemble them to more complex but useful commands.

18 Comments

  1. Adrian

    How to auto start this container with apache auto start

  2. slopjong

    Do you mean with auto (re)start at boot time?

  3. Adrian

    yes.
    When host system reboot, the apache container will auto start

  4. AFS

    Assuming “apache install apache2″ should be “apt-get install apache2″?

  5. I wrote a similar post only using Ubuntu and Passenger (with Nginx). Also left a Dockerfile, sample image on DockerHub and show users how to deploy to DigitalOcean from the command line. Please check it out.

  6. Derk

    Thank you very much!

  7. It is good to share your inspirational experiences with others so they can all develop faith and share the blessings through taking refuge in the lineage.

  8. myself

    How are the commands inside the dockerfiles executed?

  9. bhagwat

    thank you !
    created apache2 image

  10. ranjeeth

    I have build a docker container using jenkins and started the service as shown above
    docker run -d -p 9999:80 centos-http /sbin/httpd -D FOREGROUND

    everything went fine but after i log into that machine and try to attach with the container ID the image exited immediately. How can i keep the image running and i still able to connect to it?

  11. Piotrek

    What does “-D FOREGROUND” mean?
    Is it a Docker’s or Apache’s command?

  12. Ranjeeth, when you run docker with the -d flag it starts a “detached” process which should run as a daemon (i.e. keep running in the background). Check that the process started with “docker ps”.

    Piotrek, check the manual. From your shell type “man httpd” and look for the -D flag to see what it does.

  13. nei

    When add RUN /usr/sbin/apache2ctl -D FOREGROUND it not build the image properly.

    Should I use RUN or Entrypoint?

  14. Eng khalid

    dear friend
    can any one help me with issue, i install (httpd) inside docker image and install (nginx) inside another docker image all i need to start the (httpd) and (nginx) services from inside container with systemd or any technique
    best regards

  15. Hi Eng, for what it’s worth you may just be making your life harder by moving things into separate docker containers. The beauty of Docker is it’s easy to create pre-configured full-stack environments, among other things. If you try to make multiple docker containers work together you will be increasing complexity and making things more difficult to maintain. If you are looking for an easy way to manage Nginx inside a Docker container I’ve built a pre-configured image for that which you can find from my related blog post Simple websites with Jekyll and Docker. Good luck!

  16. sinead

    Thanks very much,
    I had a college project, run website through docker container. This was very helpful to get apache running.

  17. pbbhopp

    Hello, when I ran docker run -d -p 9999:80 nearmeapp-ionic231 /sbin/httpd -D FOREGROUND, or replace /sbin/https/ with /usr/sbin/apachectl, I got:
    [root@io1 cms]# docker run -d -p 9999:80 nearmeapp-ionic231 /sbin/httpd -D FOREGROUND
    1da59189f04bdb1e8b85729392519f337384cab8261653458bdf9a5b64b7671e
    docker: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused “exec: \”/sbin/httpd\”: stat /sbin/httpd: no such file or directory”.

    Please help me friends :)

Trackbacks / Pings

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>