At this point, Docker needs little introduction. Running applications in a container is all the rage right now, and the Fedora Project has been working hard to make sure that it’s easy to use Fedora to run containers, and to run Fedora inside a container. To make it even easier, the project has a set of Dockerfiles that let you get started immediately with a containerized application to build on.
The project has Dockerfile that defines more than 20 applications – ranging from Ansible to WordPress. If you haven’t worked with Dockerfiles previously, let’s take a look at using Dockerfiles and how you can build an image from them, and run your application.
The Fedora Dockerfiles are available as a package, or you can just grab them on on GitHub.
If you want to grab the package, look for the
fedora-dockerfiles package (no shocker there, huh?). They’ll be installed under
Generally, though, I recommend grabbing the Dockerfiles directly from GitHub. Those are likely to be more up-to-date, and you can just grab one file or go ahead and clone the entire repository and track any change you might make. And, of course, you could submit changes back to the project too. If you find errors, make interesting changes, or create new and interesting Dockerfiles please feel free to submit a pull request.
To clone the entire repo, do:
git clone firstname.lastname@example.org:fedora-cloud/Fedora-Dockerfiles.git
Naturally, you’ll need to have git installed. If you don’t, install the
git package (e.g.
sudo dnf install git).
Create an Image from a Dockerfile
Let’s say you have grabbed the Fedora-Dockerfiles repo from GitHub. Let’s take a look at the Nginx Dockerfile and then build it.
Reading the Dockerfile
The Dockerfile is actually quite short, just 11 lines:
FROM fedora MAINTAINER scollier <email@example.com> RUN yum -y update && yum clean all RUN yum -y install nginx && yum clean all RUN echo "daemon off;" >> /etc/nginx/nginx.conf RUN echo "nginx on Fedora" > /usr/share/nginx/html/index.html EXPOSE 80 CMD [ "/usr/sbin/nginx" ]
Some of that is probably going to look very familiar if you’ve been working with Fedora for a while. As you can see, several lines are just using
yum to update the package cache and then install the
nginx package, and then run
yum clean. Note that you could do this (and the additional
echo commands) interactively. However, it’s way more efficient to put it in a Dockerfile.
Why do we do the
yum clean each time? It removes the cache and makes the image smaller. (You can compare by building an image without the
yum clean all and see how much larger the image is.) Note that the steps you use in the build will show up if someone does a
docker history on the image, and it’s even possible to use
docker run to run an individual layer of an image.
EXPOSE directive exposes port 80 of the container to the host. By default, the container wouldn’t be listening on port 80 when you run it if you didn’t include this directive. Note that you can still use the
-p directive to expose a port at runtime, but this saves a bit of typing…
CMD directive tells Docker to run this when the container is spun up.
To sum up: This Dockerfile will tell
docker build to build a container from the fedora image, run
yum to update the package cache and then install
nginx, update the Nginx configuration and create a default landing page (index.html).
Note that it doesn’t specify the version of Fedora that should be used. If you want to specify, be sure to add the version like so:
Now we’re ready to go ahead and fire up the container.
Images vs. Containers
It may seem like a very subtle distinction, but when you first build a Dockerfile you have an image. When you actually run the image, you have a container.
Why does this matter? The simple version: images are immutable, containers are the images plus changes that are layered on them after they’re run and (potentially) modified. Even when a container is at rest (stopped) it’s still a container, and it retains things like network ports and resource limits the next time it’s started.
Make sure you’re in the
nginx directory of the repo you checked out and we’ll go ahead and build the image, like so:
sudo docker build -t username/imagename .
This command will tell Docker to do the following:
- Read the Dockerfile in current directory (the
.at the end of the command).
- Build the image using the instructions in the Dockerfile.
- Tag (
-t) the image with with the “username/imagename” you specify.
So here’s the command I use, and note that I’d usually use
jzb instead of
zonker, but the username must be at least four characters.
sudo docker build -t zonker/nginx .
This will pull down the Fedora base image, if it’s not already present, and then run the commands in the Dockerfile. When finished, you can start a container from the image.
Running the Container
Now we’re ready to start a container from the image. Let’s go ahead and fire up Nginx and point it at port 8080 on the localhost — in other words, requests coming to the host running Docker on port 8080 will redirect to the Nginx container (on port 80).
sudo docker run -d --name f21nginx -p 8080:80 zonker/nginx
Naturally the name of the image (zonker/nginx) will be different for you, so substitute whatever name/tag you chose there.
Now when you make a request on port 8080 (e.g. http://localhost:8080) it will redirect to the Nginx process running in the container on port 80. So you’ll see whatever content that Nginx is serving, in this case just the test page.
Submitting Fixes and New Dockerfiles
Have a fix or want to submit a new Dockerfile? Feel free to submit a Pull Request (PR) on GitHub.
We also welcome folks who want to test the Fedora Dockerfiles, especially as we’re ramping up towards Fedora 22. If you have questions or comments on Dockerfiles, feel free to ask on firstname.lastname@example.org.