Docker Commit 사용법 완벽 가이드! Container 변경사항을 Image로 저장하는 방법

Docker를 사용하다 보면 실행 중인 Container에서 Package를 설치하거나 설정 파일을 변경한 뒤 현재 상태를 그대로 Docker Image로 저장하고 싶은 경우가 있습니다.

이때 사용할 수 있는 명령어가 docker commit입니다.

하지만 docker commit을 처음 사용할 때 자주 발생하는 문제가 있습니다.

Container 안에서 분명히 파일이나 Database를 변경했는데 새로운 Image를 생성한 후 다시 Container를 실행하면 일부 변경사항이 사라지는 경우입니다.

이 문제를 이해하려면 Docker Image, Container Layer, Volume의 저장 구조를 먼저 이해해야 합니다.

Docker Commit이란?

docker commit은 실행 중이거나 중지된 Container의 변경사항을 새로운 Docker Image로 생성하는 명령어입니다.

기본적인 사용 방법은 다음과 같습니다.

docker commit CONTAINER IMAGE_NAME

예를 들어 web-server라는 Container의 현재 상태를 my-web:v1이라는 Image로 만들려면 다음과 같이 실행할 수 있습니다.

docker commit web-server my-web:v1

생성된 Image는 다음 명령어로 확인할 수 있습니다.

docker images

이후 새로운 Image를 이용하여 다시 Container를 생성할 수 있습니다.

docker run -d --name new-web my-web:v1

Docker Commit은 무엇을 저장할까?

Docker Container가 실행되면 Image 위에 Writable Container Layer가 추가됩니다.

구조를 단순화하면 다음과 같습니다.

Docker Image

Container Writable Layer

실행 중인 Container

Container 내부에서 파일을 생성하거나 설정 파일을 변경하면 일반적으로 Writable Layer에 변경사항이 기록됩니다.

docker commit은 이 변경사항을 기반으로 새로운 Image를 생성합니다.

예를 들어 Container 내부에서 다음과 같은 작업을 했다고 가정해보겠습니다.

apt update
apt install nginx

해당 Package 설치 내용이 Container Layer에 기록되어 있다면 docker commit을 통해 새로운 Image에 반영할 수 있습니다.

Docker Commit에서 Volume 데이터가 저장되지 않는 이유

docker commit을 사용할 때 가장 많이 혼동하는 부분입니다.

docker commit은 Container의 filesystem 변경사항을 Image로 저장하지만 Volume에 저장된 데이터까지 Image에 포함하지는 않습니다.

구조를 보면 이해하기 쉽습니다.

Container

├── Writable Layer → docker commit 포함

└── Volume → docker commit 포함되지 않음

즉 Volume은 Container Layer와 별도의 저장 공간입니다.

따라서 Volume에 저장된 파일을 변경한 후 docker commit을 실행해도 해당 데이터는 새로운 Image에 포함되지 않습니다.

MySQL에서 Docker Commit이 예상대로 동작하지 않는 이유

MySQL Container에서 이 문제가 자주 발생합니다.

MySQL 공식 Docker Image는 Database 데이터를 일반적으로 다음 경로에 저장합니다.

/var/lib/mysql

이 경로는 MySQL 데이터를 영구적으로 관리하기 위한 Volume과 관련되어 있습니다.

예를 들어 MySQL Container를 실행한 다음 Database를 생성했다고 가정해보겠습니다.

CREATE DATABASE test;

그리고 Table을 생성합니다.

USE test;

CREATE TABLE user (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);

이후 다음과 같이 Container를 Image로 만들었다고 가정해보겠습니다.

docker commit mysql-container custom-mysql:v1

새로운 Image 자체는 정상적으로 생성됩니다.

하지만 해당 Image로 새로운 Container를 실행했을 때 기존 Database와 Table이 나타나지 않을 수 있습니다.

MySQL 데이터가 Container Writable Layer가 아니라 Volume에 저장되어 있었기 때문입니다.

Docker Commit으로 Database를 저장하면 안 될까?

기술적으로 Container 상태를 Image로 저장할 수 있는 상황은 있지만 Database를 이런 방식으로 관리하는 것은 좋은 구조가 아닙니다.

Database는 지속적으로 데이터가 변경되는 Stateful Application입니다.

반면 Docker Image는 동일한 실행 환경을 반복적으로 생성하기 위한 불변에 가까운 Template 역할을 합니다.

따라서 다음과 같이 역할을 분리하는 것이 좋습니다.

Docker Image

Application 및 실행 환경 저장

Docker Volume

지속적으로 변경되는 데이터 저장

SQL Script

초기 Database와 Table 구조 정의

이렇게 역할을 분리하면 Container를 삭제하거나 다시 생성해도 데이터와 초기 설정을 체계적으로 관리할 수 있습니다.

초기 Database와 Table을 Image에 포함시키는 방법

MySQL Container가 시작될 때 특정 Database와 Table을 자동으로 생성하고 싶다면 docker commit보다 초기화 SQL Script를 사용하는 것이 좋습니다.

예를 들어 다음과 같이 init.sql 파일을 생성합니다.

CREATE DATABASE test;

USE test;

CREATE TABLE user (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);

그리고 Dockerfile을 작성합니다.

FROM mysql:8.0

COPY init.sql /docker-entrypoint-initdb.d/

Image를 Build합니다.

docker build -t custom-mysql:v1 .

Container를 실행합니다.

docker run -d \
  --name mysql-server \
  -e MYSQL_ROOT_PASSWORD=password \
  custom-mysql:v1

Container가 처음 초기화될 때 /docker-entrypoint-initdb.d/에 있는 SQL Script가 실행되면서 필요한 Database와 Table이 생성됩니다.

Dockerfile과 Docker Commit의 차이

docker commit과 Dockerfile은 모두 새로운 Image를 만드는 데 사용할 수 있지만 목적과 관리 방식에는 차이가 있습니다.

docker commit은 현재 Container 상태를 빠르게 Image로 저장할 때 편리합니다.

하지만 어떤 명령어와 설정 변경을 통해 해당 Image가 만들어졌는지 나중에 파악하기 어렵다는 단점이 있습니다.

Dockerfile은 Image 생성 과정을 코드로 기록합니다.

예를 들어 다음과 같습니다.

FROM ubuntu:24.04

RUN apt-get update && \
    apt-get install -y nginx

COPY nginx.conf /etc/nginx/nginx.conf

이렇게 구성하면 Image가 어떤 과정으로 만들어졌는지 Dockerfile만 확인해도 알 수 있습니다.

따라서 운영 환경에서는 docker commit보다 Dockerfile을 이용하여 Image Build 과정을 관리하는 것이 일반적으로 더 적합합니다.

Docker Commit이 유용한 경우

그렇다고 docker commit을 사용하면 안 되는 것은 아닙니다.

테스트 중인 Container 상태를 임시로 저장하거나 Container에서 여러 설정을 실험한 후 현재 상태를 빠르게 Image로 보관할 때 유용할 수 있습니다.

예를 들어 다음과 같은 상황입니다.

개발 및 테스트 환경의 임시 Snapshot

설정 변경 결과 테스트

문제 분석을 위한 Container 상태 보존

Dockerfile 작성 전 임시 Image 생성

다만 장기간 운영하거나 여러 사람이 동일한 환경을 재현해야 한다면 Dockerfile을 사용하는 편이 관리하기 좋습니다.

Docker Commit 사용 전 확인할 사항

docker commit을 실행하기 전에 변경된 데이터가 어디에 저장되어 있는지 확인해야 합니다.

Container의 Mount 정보를 확인하려면 다음 명령어를 사용할 수 있습니다.

docker inspect CONTAINER_NAME

출력 결과에서 Mounts 항목을 확인하면 Volume이나 Bind Mount가 어떤 경로에 연결되어 있는지 확인할 수 있습니다.

MySQL을 사용하고 있다면 특히 /var/lib/mysql이 Volume으로 연결되어 있는지 확인하는 것이 중요합니다.

Volume 목록은 다음 명령어로 확인할 수 있습니다.

docker volume ls

특정 Volume의 자세한 정보는 다음과 같이 확인할 수 있습니다.

docker volume inspect VOLUME_NAME

Docker Image, Container, Volume의 역할 구분

Docker를 안정적으로 운영하려면 세 가지의 역할을 구분하는 것이 중요합니다.

Image는 Container 실행 환경을 정의합니다.

Container는 Image를 기반으로 실제 Application을 실행합니다.

Volume은 Container와 별도로 유지해야 하는 데이터를 저장합니다.

따라서 일반적인 구조는 다음과 같습니다.

Dockerfile

Docker Image

Container

Application 실행

그리고 지속적으로 보관해야 하는 데이터는 별도의 Volume에 저장합니다.

Container가 삭제되더라도 Volume을 유지하면 데이터를 다시 연결하여 사용할 수 있습니다.

Docker Commit보다 Dockerfile을 권장하는 이유

운영 환경에서 Dockerfile을 사용하는 가장 큰 이유는 재현성입니다.

docker commit으로 만든 Image는 Container 안에서 어떤 명령어를 실행했고 어떤 파일을 변경했는지 정확하게 관리하기 어렵습니다.

반면 Dockerfile은 Image 생성 과정을 코드로 기록할 수 있습니다.

Git과 함께 관리하면 언제 어떤 설정이 변경되었는지도 추적할 수 있습니다.

따라서 실제 서버 환경에서는 다음과 같은 구조가 좋습니다.

Dockerfile 작성

Git으로 변경 이력 관리

docker build 실행

Docker Image 생성

Container 배포

Volume을 이용한 데이터 관리

마무리

docker commit은 Container의 현재 filesystem 변경사항을 새로운 Docker Image로 저장할 수 있는 편리한 명령어입니다.

하지만 모든 데이터가 저장되는 것은 아닙니다.

Volume이나 Bind Mount처럼 Container filesystem 외부에 저장된 데이터는 docker commit으로 생성한 Image에 포함되지 않습니다.

특히 MySQL처럼 데이터를 별도의 경로에 지속적으로 저장하는 Application에서는 이 차이를 반드시 이해해야 합니다.

초기 Database와 Table 구조가 포함된 MySQL 환경을 반복해서 생성하고 싶다면 Database 자체를 docker commit으로 저장하기보다 SQL Script와 Dockerfile을 이용하여 초기화 과정을 자동화하는 것이 좋습니다.

실제 운영 데이터는 Volume에 저장하고 Application 환경과 초기 설정은 Dockerfile과 Image로 관리하면 Docker 환경을 더욱 안정적으로 운영할 수 있습니다.

댓글 남기기