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
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
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
to update the package cache and then install the
package, and then run
. Note that you could do this (and the additional
commands) interactively. However, it’s way more efficient to put it in a Dockerfile.
Why do we do the
each time? It removes the cache and makes the image smaller. (You can compare by building an image without the
and see how much larger the image is.) Note that the steps you use in the build will show up if someone does a
on the image, and it’s even possible to use
to run an individual layer of an image.
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
directive to expose a port at runtime, but this saves a bit of typing…
directive tells Docker to run this when the container is spun up.
To sum up: This Dockerfile will tell
to build a container from the fedora image, run
to update the package cache and then install
, 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
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 (
) the image with with the “username/imagename” you specify.
So here’s the command I use, and note that I’d usually use
, 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.
Why run yum clean all after both yum commands? Shouldn’t you just run it once after the last yum usage?
No, because the layer will still have the cache – each RUN command creates a new layer. Try it yourself and see how the image size differs.
Formatting squashed 2 dashes into one en dash in:
When will official Fedora 22 file coming out?
Fedora 22 is in alpha, so, knowing the Fedora crew’s speed, “beta” can’t be far behind 😉 …
It seems a bit pointless to do:
RUN yum -y update && yum clean all
RUN yum -y install nginx && yum clean all
When you could just use:
RUN yum -y update
RUN yum -y install nginx
RUN yum clean all
Why pull a full copy of the repo metadata twice?
Don’t answer that — it was a dumb question. I momentarily forgot that Docker makes a snapshot for each command.
For those on CoreOS: be aware there’s presently a bug that causes build to fail with a checksum error: