
Whether you’re just getting started containerizing applications or you’re diving deeper into Kubernetes development, knowing how to create your first Docker images for applications is an essential skill. In this guide, you’ll learn how to create Docker images so you can deploy your own applications and make them available to other people.
Table of Contents
- How Docker images work
- How do I create a Docker image?
- Creating a new Docker image from an existing container
- Using a Dockerfile
- Additional Mirantis Docker image resources
- Moving forward
How Docker images work
Before learning to create Docker images, the first thing that we need to understand is how Docker images themselves work.
The key to a Docker image is that it’s a layered file system. In other words, if you start out with an image that’s just the operating system (say Windows) and then add an application (say Nginx), you’ll wind up with something like this:
As you can see, the difference between IMAGE1 and IMAGE2 is just the application itself, and then IMAGE4 has the changes made on layers 3 and 4. So in order to create an image, you are basically starting with a base image and defining the changes to it.
I hear you asking, “But what if I want to start from scratch?” Well, let’s define “from scratch.” Chances are, you mean that you want to start with a clean operating system and go from there. Well, in most cases there’s a base image already available to do exactly that.
But maybe you want to spin up a bare-bones foundation for your new container…using Docker’s scratch image. In that case, skip forward to the Using a Dockerfile section. (For further information on creating a Docker base image, including instructions on using tar to package a parent image, check out the Docker docs.)
How do I create a Docker image?
In this guide, we’re going to look at two methods for creating a new Docker image:
- Create a Docker image from an existing container: In this case, you start with an existing image, customize it with the changes you want, then build a new image from it.
- Use a Dockerfile: In this case, you use a file of instructions — the Dockerfile — to specify the base image and the changes you want to make to it.
Let’s start by creating a new image from an existing container.
Creating a new Docker image from an existing container
When it comes to Docker, getting started can be pretty straightforward. In this example, we’re going to start with an image that includes the nginx web application server and PHP. To that, we’re going to add support for reading RSS data using an open-source package called SimplePie (available for download at GitHub). We’ll then make a new image out of the altered container.
Set up Docker and Docker Hub
The very first step is to make sure that your system has Docker Engine installed. For Windows and Mac users, the process has changed with the introduction of Docker Desktop. You can follow the instructions here to install Docker.
Next, you’ll need to get the base image. For this tutorial, that’s webdevops/php-nginx, which you can find in the Docker Hub repository — in order to “pull” it, you’ll need a Docker Hub ID. If you don’t have one already, go to https://hub.docker.com and create a free account.
Create the original Docker container
The first thing we need to do is instantiate the original base image, or have Docker create a container from an image.
Go to the command line where you have Docker installed and log in to the Docker Hub:
# docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: nickchase Password: Login Succeeded
We’re going to start with the base image and have Docker start a container. Instantiate webdevops/php-nginx:
# docker run -dP webdevops/php-nginx
The -dP flag makes sure that the container runs in the background, and that the ports on which it listens are made available.
Make sure the container is running:
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1311034ca7dc webdevops/php-nginx "/opt/docker/bin/entr" 35 seconds ago Up 34 seconds 0.0.0.0:32822->80/tcp, 0.0.0.0:32821->443/tcp, 0.0.0.0:32820->9000/tcp small_bassi
A couple of notes here. First off, because we didn’t specify a particular name for the container, Docker assigned one. In this example, it’s small_bassi. Second, notice that there are 3 open ports: 80, 443, and 9000, and that they’ve been mapped to other ports (in this case 32822, 32821, and 32820, respectively — on your machine these ports will be different). This makes it possible for multiple containers to be “listening” on the same port on the same host machine. So if we were to try and access a web page hosted by this container, we’d do it by accessing:
So far, though, there aren’t any pages to access. Let’s fix that.
Create a file on the container
In order for us to test this container, we need to create a sample PHP file. We’ll do that by logging into the container and creating a file.
- Login to the container
# docker exec -it small_bassi /bin/bash root@1311034ca7dc:/#
Using exec with the -it switch creates an interactive session for you to execute commands directly within the container. In this case, we’re executing /bin/bash, so we can do whatever else we need to.
- The document root for the nginx server in this container is at /app, so go ahead and create the /app/index.php file:
vi /app/index.php
- Add a simple PHP routine to the file and save it:
for ($i; $i < 10; $i++){ echo "Item number ".$i."\n"; } ?>
- Now exit the container to go back to the main command line:
root@1311034ca7dc:/# exit
- Now let’s test the page. To do that, execute a simple curl command:
# curl http://localhost:32822/index.php Item number Item number 1 Item number 2 Item number 3 Item number 4 Item number 5 Item number 6 Item number 7 Item number 8 Item number 9
Now it’s time to go ahead and add RSS.
Make changes to the container
Now that we know PHP is working we can go ahead and add RSS support using the SimplePie package. To do that, we’ll simply download it to the container and install it.
- The first step is to log back into the container:
# docker exec -it small_bassi /bin/bash root@1311034ca7dc:/#
- Next go ahead and use curl to download the package, saving it as a zip file:
root@1311034ca7dc:/# curl https://codeload.github.com/simplepie/simplepie/zip/1.4.3 > simplepie1.4.3.zip
- Now you need to install it. To do that, unzip the package, create the appropriate directories, and copy the necessary files into them as follows:
root@1311034ca7dc:/# unzip simplepie1.4.3.zip root@1311034ca7dc:/# mkdir /app/php root@1311034ca7dc:/# mkdir /app/cache root@1311034ca7dc:/# mkdir /app/php/library root@1311034ca7dc:/# cp -r s*/library/* /app/php/library/. root@1311034ca7dc:/# cp s*/autoloader.php /app/php/. root@1311034ca7dc:/# chmod 777 /app/cache
- Now we just need a test page to make sure that it’s working. Create a new file in the /app directory:
root@1311034ca7dc:/# vi /app/rss.php
- Now add the content for the sample file. (This file is excerpted from the SimplePie website, but I’ve cut it down for brevity’s sake, since it’s not really the focus of what we’re doing. Please see the original version for explanatory line comments.)
require_once('php/autoloader.php'); $feed = new SimplePie(); $feed->set_feed_url("http://rss.cnn.com/rss/edition.rss"); $feed->init(); $feed->handle_content_type(); ?>
Sample SimplePie Page get_title(); ?>
get_description(); ?>