How to Create a Docker Image From a Container | DataSet
How to Create a Docker Image From a Container | DataSet
Blog Platform Solutions Pricing Blog Customers About Login Get a Demo
C O N TA I N E R S A N D K U B E R N E T E S , T I P S & T R I C K S
In this article, I’ll provide step-by-step instructions on how to create a Docker container,
modify its internal state, and then save the container as an image.
This is really handy when you’re working out how an image should be constructed
because you can just keep tweaking a running container until it works as you want it to.
When you’re done, just save it as an image. You can use the following guide to
customize and deploy the DataSet agent for common tasks such as adding parsers for
your log files, adding redaction/sampling rules, running custom plugins, or mounting
volumes for application log files.
Before we jump right into it, we'd like to invite you to a relevant webinar on how to get
the most value out of your Kubernetes Audit logs. If you run Docker containers in K8s
environments, we will cover the best practices to implement comprehensive, secure,
and efficient audit logs in production Kubernetes clusters. We look forward to seeing in
the webinar.
The Docker create command will create a new container for us from the command line:
Here we have requested a new container named nginx_base with port 80 exposed to
localhost. We are using nginx:alpine as a base image for the container.
If you don’t have the nginx:alpine image in your local docker image repository, it will
download automatically. When this happens, you will see something like this:
➜ ~ docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
amitsharma/nginx-reverse-proxy v1 1037dc5f8db4 3 weeks ago 142MB
nginx-reverse-proxy latest 1037dc5f8db4 3 weeks ago 142MB
amitsharma/web-server-app v1 09a0abf08e08 3 weeks ago 58.3MB
web-server-app latest 09a0abf08e08 3 weeks ago 58.3MB
nginx alpine 51696c87e77e 4 weeks ago 23.4MB
~ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c365af6303e4 nginx:alpine "/docker-entrypoint.…" 6 minutes ago Created nginx_base
Now visit http://localhost with your browser. You will see the default “Welcome to
nginx!” page. We are now running an nginx container.
In order to keep things as simple as possible, we are just going to copy a new index.html
file onto the server. You could do practically anything you wanted here.
Let’s create a new index.html file and copy it onto the running container. Using an editor
on your machine, create an index.html file in the same directory that you have been
running Docker commands from.
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
Then save the file and return to the command line. We will use the docker cp command
to copy this file onto the running container.
Now reload your browser or revisit http://localhost. You will see the message “Hello
World!” in place of the default nginx welcome page.
However, we want to know how to save this container as an image so we can make
other containers based on this one. The Docker commands to do this are quite simple.
To save a Docker container, we just need to use the docker commit command like this:
➜ ~ docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 0c17f0798823 About a minute ago 23.4MB
amitsharma/nginx-reverse-proxy v1 1037dc5f8db4 3 weeks ago 142MB
nginx-reverse-proxy latest 1037dc5f8db4 3 weeks ago 142MB
amitsharma/web-server-app v1 09a0abf08e08 3 weeks ago 58.3MB
web-server-app latest 09a0abf08e08 3 weeks ago 58.3MB
nginx alpine 51696c87e77e 4 weeks ago 23.4MB
You can see there is a new image there. It does not have a repository or tag, but it exists.
This is an image created from the running container. Let’s tag it so it will be easier to
find later.
And if we look at the index of images again, we can see that the <None>s were replaced:
We can actually use complicated tags here with version numbers and all the other
fixings of a tag command, but for our example, we’ll just create an image with a
meaningful name.
This command effectively commits and tags at the same time, which is helpful but not
required.
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c365af6303e4 nginx:alpine "/docker-entrypoint.…" 33 minutes ago Up 25 minutes 0.0.0.0:80->80/tcp nginx_base
Let’s stop and remove the Docker container that is currently running and delete it.
➜ ~ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Now, let’s create a new container based on the image we just created and start it.
Note that docker run is the equivalent of executing docker create followed by docker
start; we are just saving a step here.
The -d option tells Docker to run the container detached so we get our command
prompt back.
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7ca08e03862d hello_world_nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp hello_world
As you can see, the index.html page now shows the “Hello World!” message just like we
wanted.
For example, we might want to record who the author of our image is or capture a
commit message telling us about the state of the image.
These are all controlled through optional parameters to the commit command.
Let’s go back to our original running container. We are going to use a slightly different
command here to make cleanup easier:
This command will run the image nginx:alpine with the name nginx_base; the creation
of the image will be included in the command execution.
The –rm will cause the container to be deleted when it is shut down. The -d tells the
command line client to run in detached mode. This will allow us to run other commands
from the same terminal.
So if you visit http://localhost now, you should see the default nginx welcome page.
We went through changing things about the running container above, so I won’t repeat
that work here; instead, we want to look at the various options around the commit sub-
command.
We will use the docker inspect command to get the details of the image and grep out
the author line.
So if we use the author option on the docker commit command, we can set the value of
the author field.
Using the image name, we can look at the history of the Docker image to see our
message. Here we are using the docker history command to show the change history of
the image we created:
Notice that we see the entire history here, and the first entry is from our commit of the
running container. The first line listed shows our commit message in the rightmost
column.
Let’s remove this image and check out the other options:
For our little play container this is unimportant, but you might be doing something like
capturing an image of a production system where pausing isn’t an option.
You can add the –pause=false flag to the commit command, and the image will be
created from the container without the pause.
If you don’t pause the container, you run the risk of corrupting your data.
For example, if the container is in the midst of a write operation, the data being written
could be corrupted or come out incomplete. That is why, by default, the container gets
paused before the image is created.
Let’s remove this image and check out the other options:
You can change any of the following settings of the image during the commit process:
CMD
ENTRYPOINT
ENV
EXPOSE
LABEL
ONBUILD
USER
VOLUME
WORKDIR
So we will just play with one of those for a moment. The NGINX_VERSION and EXPOSE
could cause issues with container startup, so we will mess with the command line (CMD)
executed by the container.
Nginx allows us to pass the -T command line argument that will dump its configuration
to standard out. Let’s make an image with an alternate CMD value as follows:
The configuration for the nginx process will be dumped to standard out when you
execute this command. You can scroll back several pages to find the command we
executed.
As I showed above, there are many helpful options available, too. The Docker CLI has
many other power commands. If you like, you can explore some of them here.
DataSet is the best-of-breed log analytics solution for dynamic container environments.
It is the only solution that provides unmatched performance and scale while optimizing
the total cost of ownership.
To find out more about working with Docker and DataSet, check out these resources:
Installing the DataSet Agent in Docker
Configure the DataSet Agent for Docker
Subscribe for more content like this directly to your inbox Business Email
By clicking Subscribe, I agree to the use of my personal data in accordance with SentinelOne Privacy Policy. SentinelOne will not sell, trade, lease, or rent your personal data to third parties.