Note: The docker commit command has some special applications beyond learning, such as saving the scene after an intrusion. However, do not use docker commit to customise images; customising images should be done using Dockerfile.
Images are the foundation of containers, and every time you run docker run you specify which image to use as the foundation for the container to run on. In the previous example, we used images from the Docker Hub. These mirrors can be used directly to meet certain needs, but when they can’t be used directly, we need to customise them.
Mirroring is a multi-layer storage, where each layer is a modification of the previous layer. Containers, on the other hand, are also multiple layers of storage, which use images as the base layer and add another layer on top of it as the runtime storage layer of the container.
Let’s take a custom Web server as an example to show how the image is built.
docker run --name webserver -d -p 80:80 nginx
This will start a container with an nginx image, named webserver, mapped to port 80 so that we can use a browser to access the nginx server.
If you are running Docker locally, you can directly access: http://localhost. If you are installing Docker on a virtual machine or cloud server, you need to change localhost to the address of the virtual machine or the actual cloud server.
If we go directly to the browser, we will see the default Nginx welcome page.

Now, let’s say we hate the welcome page so much that we want to change it to welcome Docker. We can use docker exec to go into the container and change its contents.
docker exec -it webserver bash
echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
exit
We entered the webserver container interactively and executed bash commands, which gave us a working Shell.
Then, we use <h1>Hello, Docker! < / h1 > covered the/usr/share/nginx/HTML/index. The HTML content.
Now if we refresh the browser, we will see that the content has changed.

We changed the container file, which means we changed the storage layer of the container. You can see the changes with the docker diff command.
PS C:\Users\30277> docker diff webserver
C /root
A /root/.bash_history
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
C /run
A /run/nginx.pid
C /usr
C /usr/share
C /usr/share/nginx
C /usr/share/nginx/html
C /usr/share/nginx/html/index.html
Now that we’ve customized our change, we want to save it as an image.
Keep in mind that when we run a container (if not using volumes), any file changes we make will be recorded in the container storage layer. Docker provides a docker commit command to save the container’s storage layer as an image. In other words, we are stacking the container’s storage layer on top of the original image. Later when we run this new image, we will have the last changes to the original container.
The docker commit syntax is:
docker commit [options] < container ID or container name >[< repo name >[:< tag >]]
We can save the container as an image with the following command:
docker commit --author "Zeming Wang <wzm970527@gmail.com>" \
--message "edit the index page" webserver nginx:v2
Where –author specifies the author of the change, and –message logs the change. This is similar to git version control, but this information can be omitted and left blank.
We can see this new custom image in docker image ls:
PS C:\Users\30277> docker image ls nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 aa0738f89185 About a minute ago 188MB
nginx latest e784f4560448 3 weeks ago 188MB
We can also use docker history to look specifically at the history of the image, and if we compare the history of nginx:latest, we’ll see that we’ve added the layer we just committed.
PS C:\Users\30277> docker history nginx:v2
IMAGE CREATED CREATED BY SIZE COMMENT
aa0738f89185 3 minutes ago nginx -g daemon off; 1.19kB edit the index page
e784f4560448 3 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
<missing> 3 weeks ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0
<missing> 3 weeks ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
<missing> 3 weeks ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
<missing> 3 weeks ago COPY 30-tune-worker-processes.sh /docker-ent… 4.62kB buildkit.dockerfile.v0
<missing> 3 weeks ago COPY 20-envsubst-on-templates.sh /docker-ent… 3.02kB buildkit.dockerfile.v0
<missing> 3 weeks ago COPY 15-local-resolvers.envsh /docker-entryp… 336B buildkit.dockerfile.v0
<missing> 3 weeks ago COPY 10-listen-on-ipv6-by-default.sh /docker… 2.12kB buildkit.dockerfile.v0
<missing> 3 weeks ago COPY docker-entrypoint.sh / # buildkit 1.62kB buildkit.dockerfile.v0
<missing> 3 weeks ago RUN /bin/sh -c set -x && groupadd --syst… 113MB buildkit.dockerfile.v0
<missing> 3 weeks ago ENV PKG_RELEASE=1~bookworm 0B buildkit.dockerfile.v0
<missing> 3 weeks ago ENV NJS_RELEASE=3~bookworm 0B buildkit.dockerfile.v0
<missing> 3 weeks ago ENV NJS_VERSION=0.8.4 0B buildkit.dockerfile.v0
<missing> 3 weeks ago ENV NGINX_VERSION=1.25.5 0B buildkit.dockerfile.v0
<missing> 3 weeks ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:5aaace706aa00ff97… 74.8MB
Now that the new image is customized, we can run it.
docker run --name web2 -d -p 81:80 nginx:v2
Here we name the new service web2 and map it to port 81. Visit http://localhost:81 to see the results, which should look the same as the modified webserver.
This is the first time we’ve done a custom image, using the docker commit command, which manually adds a new layer to the old image to form a new image, so it should be more intuitive to store multiple layers of images.
Be careful with docker commit
docker commit is an intuitive way to understand the concept of image layering, but it is not used in real life.
First of all, if you look carefully before docker diff webserver results, you will find that in addition to really want to change the /usr/share/nginx/HTML/index.html file. As a result of the command execution, there are many files were changed or added. This is just the bare minimum. If you were to install packages and build them, a lot of extranous stuff would be added, which would make the image very bloated.
In addition, using docker commit means that all operations on the image are black-box operations, and the resulting image is also called a black-box image, in other words, no one else knows what commands were executed and how the image was generated. Moreover, even the person who made the image could not remember the exact operation after a while. The maintenance of this black box image is very painful.
Also, recall that mirroring uses the concept of hierarchical storage, all layers before it are immutable except the current one, meaning that the result of any change is simply marking, adding, and modifying the current layer, not the one above it. If you use docker commit to make an image and make changes later, each change will make the image more bloated. The items you remove from the previous layer are not lost, they will always follow the image, even if they are not accessible. This makes the image even more bloated.
0 Comments