Back to Engineering Notes
DockerEngineering Note

7. Create a Docker Image From Container

Create a new Docker image from an existing container using the docker commit command.

# Day 7: Create a Docker Image From a Container

🎯 Objective

Create a new Docker image from an existing container using the docker commit command.

The basic command is:

bash
docker commit <container_name> <image_name>:<tag>

This captures changes made inside a container and saves them as a reusable Docker image.


🧠 Concept

Normally, Docker follows this flow:

plain text
Docker Image
     │
     │ docker run
     ▼
Container

An image is used to create a container.

However, docker commit allows us to do the reverse:

plain text
Container
     │
     │ docker commit
     ▼
New Docker Image

This is useful when you:

Modify a container manually
Install packages inside a container
Change configuration
Want to save the container's current filesystem state as an image

📦 Step 1: Check Existing Containers

List running containers:

bash
docker ps

To include stopped containers:

bash
docker ps -a

Example:

plain text
CONTAINER ID   IMAGE    COMMAND   STATUS        NAMES
a12bc34def56   ubuntu   "bash"    Up 5 minutes  dev-container

In this example, the container name is:

plain text
dev-container

🔧 Step 2: Make Changes Inside the Container

If needed, enter the running container:

bash
docker exec -it dev-container bash

For example, install a package:

bash
apt update
apt install -y nginx

Then exit:

bash
exit

The container now has changes that were not part of the original image.

plain text
ubuntu image
     │
     │ docker run
     ▼
dev-container
     │
     ├── Install Nginx
     ├── Add files
     └── Change configuration

🖼️ Step 3: Create an Image From the Container

Use:

bash
docker commit dev-container dev-image:v1

Syntax

bash
docker commit <container_name> <image_name>:<tag>

Command Breakdown

plain text
docker commit

Creates a new image from a container's changes.

plain text
dev-container

The source container.

plain text
dev-image

The new image repository/name.

plain text
v1

The image tag.


⚙️ How docker commit Works

Suppose we start with:

plain text
ubuntu:latest

Create a container:

plain text
ubuntu:latest
     │
     │ docker run
     ▼
dev-container

Then make changes:

plain text
dev-container
     │
     ├── Install packages
     ├── Add files
     └── Modify configuration

Commit the container:

bash
docker commit dev-container dev-image:v1

Result:

plain text
ubuntu:latest
     │
     │ docker run
     ▼
dev-container
     │
     │ Changes
     │
     │ docker commit
     ▼
dev-image:v1

The new image can now be used to create other containers.


🔍 Step 4: Verify the New Image

List Docker images:

bash
docker images

or:

bash
docker image ls

Example:

plain text
REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
dev-image     v1        abc123def456   10 seconds ago   180MB
ubuntu        latest    def456abc123   ...              ...

The important entry is:

plain text
dev-image:v1

🚀 Step 5: Test the New Image

Create a new container from the committed image:

bash
docker run -it dev-image:v1 bash

You can then verify that your previous changes exist.

For example:

bash
nginx -v

If Nginx was installed before the commit, it should also exist in containers created from the new image.


🏷️ Image Naming Format

Docker images commonly follow:

plain text
<repository>:<tag>

For example:

plain text
dev-image:v1

where:

plain text
Repository → dev-image
Tag        → v1

Other examples:

plain text
myapp:v1
myapp:v2
myapp:latest
nginx:custom
ubuntu:configured

If no tag is specified, Docker uses:

plain text
latest

For example:

bash
docker commit dev-container dev-image

is effectively tagged as:

plain text
dev-image:latest

📝 Optional: Add Commit Information

You can include an author:

bash
docker commit -a "Developer" dev-container dev-image:v1

You can also add a commit message:

bash
docker commit \
  -a "Developer" \
  -m "Install nginx" \
  dev-container \
  dev-image:v1

This provides additional metadata about why the image was created.


🆚 docker commit vs Dockerfile

docker commit is useful for quick snapshots and learning, but for normal development and production environments, a Dockerfile is usually preferred.

Docker Commit

plain text
Container
    ↓
Manual changes
    ↓
docker commit
    ↓
Image

Advantages:

Quick
Easy to experiment with
Useful for snapshots
Useful for troubleshooting

Disadvantage:

Manual changes are difficult to reproduce

Dockerfile

plain text
Dockerfile
    ↓
docker build
    ↓
Image

Example:

docker
FROM ubuntu:latest

RUN apt update && apt install -y nginx

Then:

bash
docker build -t dev-image:v1 .

A Dockerfile is better for production because the image creation process is documented and repeatable.


⚠️ Important Notes

docker commit creates an image from a container's filesystem changes.
The source container can be referenced by container name or container ID.
Use <image>:<tag> to give the new image a meaningful version.
If no tag is provided, Docker uses latest.
Data stored in mounted volumes is not included as normal container filesystem changes in the committed image.
docker commit is useful for quick snapshots and experiments.
Prefer a Dockerfile for repeatable production image builds.

⚙️ Complete Workflow

Check containers:

bash
docker ps -a

Create the image:

bash
docker commit container_name image_name:tag

Verify:

bash
docker image ls

Test the new image:

bash
docker run -it image_name:tag sh

🧪 Validation Checklist

[ ] Source container exists
[ ] Required changes made inside container
[ ] Container name or ID identified
[ ] docker commit executed successfully
[ ] New image created with correct name
[ ] Correct image tag applied
[ ] New image visible in docker image ls
[ ] New container can be created from the image

📌 Summary

The core command is:

bash
docker commit <container_name> <image_name>:<tag>

Example:

bash
docker commit dev-container dev-image:v1

The complete flow is:

plain text
Existing Image
     │
     │ docker run
     ▼
Container
     │
     ├── Install packages
     ├── Modify files
     └── Configure application
     │
     │ docker commit
     ▼
New Docker Image
     │
     │ docker run
     ▼
New Container

The key takeaway is:

> docker commit captures a container's filesystem changes and creates a new reusable Docker image from them. For repeatable builds, prefer a Dockerfile and docker build.