The administrator may decide that building interactively is tedious and error-prone. Instead the administrator could create a Dockerfile that layers on the Apache Web server and the web site content in one build.
The docker run command must specify an IMAGE to derive the container from. An image developer can define image defaults related to:
- detached or foreground running
- container identification
- network settings
- runtime constraints on CPU and memory
Detached vs foreground
When starting a Docker container, you must first decide if you want to run the container in the background in a “detached” mode or in the default foreground mode:
To start a container in detached mode, you use -d=true or just -d option. By design, containers started in detached mode exit when the root process used to run the container exits.
Do not pass a service x start command to a detached container. For example, this command attempts to start the nginx service.
$ docker run -d -p 80:80 my_image service nginx start
This succeeds in starting the nginx service inside the container. However, it fails the detached container paradigm in that, the root process (service nginx start) returns and the detached container stops as designed. As a result, the nginx service is started but could not be used.
Instead, to start a process such as the nginx web server do the following:
$ docker run -d -p 80:80 my_image nginx -g 'daemon off;'
In foreground mode (the default when -d is not specified), docker run can start the process in the container and attach the console to the process’s standard input, output, and standard error.
It can even pretend to be a TTY (this is what most command line executables expect) and pass along signals.
You can specify to which of the three standard streams (STDIN, STDOUT, STDERR) you’d like to connect instead, as in:
$ docker run -a stdin -a stdout -i -t ubuntu /bin/bash
For interactive processes (like a shell), you must use -i -t together in order to allocate a tty for the container process. -i -t is often written -it as you’ll see in later examples.
Create one mysite.tar with some dummy index.html and images.
A good practice is to make a sub-directory with a related name and create a Dockerfile in that directory. E.g. a directory called mongo may contain a Dockerfile for a MongoDB image, or a directory called httpd may container an Dockerfile for an Apache web server. Copy or create all other content that you wish to add to the image into the new directory. Keep in mind that the ADD directive context is relative to this new directory.
# mkdir httpd # cp mysite.tar httpd/
Create the Dockerfile in the httpd directory. This Dockerfile will use the same base image as the interactive command fedora:
FROM fedora MAINTAINER Rajesh Kumar email: firstname.lastname@example.org # Update the image with the latest packages (recommended) RUN yum update -y; yum clean all # Install Apache Web Server RUN yum install -y httpd; yum clean all # Add the tar file of the web site ADD mysite.tar /tmp/ # Docker automatically extracted. So move files to web directory RUN mv /tmp/mysite/* /var/www/html EXPOSE 80 ENTRYPOINT [ "/usr/sbin/httpd" ] CMD [ "-D", "FOREGROUND" ]
Build this Dockerfile from the new httpd directory and run it:
# docker build --rm -t newsite httpd/ # docker run -d -P newsite
The container build process builds a series of temporary image layers based on the directives in the Dockerfile. These temporary layers are cached so if you make modifications to the content tarball, it won’t completely rebuild and update the Fedora image. Since each directive is a new layer, you could reduce the number of layers by combining the RUN yum directives into a single RUN directive:
RUN yum -y install httpd && yum -y update; yum clean all
Planning your layers will determine how many layers need to be recreated on each build of the container.