docker commit

컨테이너의 파일 변경 사항이나 설정의 변경 사항을 적용한 새 이미지를 만드는 방법입니다.

주의사항
-커밋에는 마운트된 볼륨에 포함된 어떤 데이터도 포함되지 않습니다.
-기본적으로 커밋되는 컨테이너와 해당 프로세스는 커밋되는 동안 일시 중지됩니다. (커밋 과정에서 데이터 손상 발생 가능성 줄이기 위함. 중지되는 게 싫을 경우 –pause false 옵션 적용할 것)

기본 명령어

1
2
3
4
5
# full
docker container commit [OPTIONS] CONTAINER이름혹은ID [REPOSITORY:TAG]

# alias
docker commit [OPTIONS] CONTAINER이름혹은ID [REPOSITORY:TAG]

기본 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# commit 전 image 리스트
docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
ubuntu       18.04     f9a80a55f492   2 months ago     63.2MB

# container commit
docker ps
>> CONTAINER ID   IMAGE          ...  CREATED     STATUS      PORTS    NAMES
>> 1234567891     ubuntu:18.04   ...  2 min ago   up 2 sconds 0.0....  test

docker commit -a "작성자" -m "커밋 메세지" test test:0.0.1

# commit 후 image 리스트
docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
test         0.0.1     45b6a2956c40   40 seconds ago   228MB
ubuntu       18.04     f9a80a55f492   2 months ago     63.2MB

docker commit 옵션

옵션 default 설명
-a, –author   작성자(예: John Hannibal Smith <hannibal@a-team.com>)
-c, –change   생성된 이미지에 Dockerfile 명령어 적용
-m, –message   커밋 메시지
-p, –pause true 커밋 중 컨테이너 일시 중지

change 옵션

생성된 이미지에 Dockerfile 명령어를 적용합니다. 쉽게 말해, 컨테이너를 이미지로 커밋하면서 환경변수를 바꾸거나, 기본 실행 커맨드를 변경할 수 있습니다. 아래 예시를 보죠.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# change 전 상태
docker ps
>> CONTAINER ID  IMAGE         COMMAND    ...  PORTS   NAMES
>> c3f279d17e0a  ubuntu:22.04  /bin/bash  ...          desperate_dubinsky
>> 197387f1b436  ubuntu:22.04  /bin/bash  ...          focused_hamilton

# commit + change
# (1) 컨테이너 실행시 커맨드를 변경함
# (2) 80번 포트를 사용함
# 이미지 이름은 testimage:version4
docker commit --change='CMD ["apachectl", "-DFOREGROUND"]' -c "EXPOSE 80" c3f279d17e0a  svendowideit/test:v4
>> f5283438590d

# 새로이 만든 이미지로 docker run
docker run -d svendowideit/test:v4
>> 893737..

# docker run 후 상태
docker ps
>> CONTAINER ID  IMAGE    COMMAND                ...  PORTS    NAMES
>> 89373736e2e7  test:v4  "apachectl -DFOREGROU" ...  80/tcp   distracted_fermat
>> c3f279d17e0a  ubun...  /bin/bash              ...           desperate_dubinsky
>> 197387f1b436  ubun...  /bin/bash              ...           focused_hamilton

예시를 해석하면 아래와 같습니다.

명령어 설명
docker commit 실행중인 컨테이너를 이미지화(커밋) 한다.
–change, -c 생성된 이미지에 Dockerfile 명령어 적용
[“apachectl”, “-DFOREGROUND”] Apach HTTP 서버를 포그라운드로 실행한다.

컨테이너에 포그라운드로 실행되는 프로세스가 없을 경우
컨테이너가 종료되기 때문에, 백그라운드가 아닌 포그라운드로
실행시키는 것으로 보인다.
“EXPOSE 80” 컨테이너가 내부적으로 80 포트를 사용함을 나타낸다.

단, 컨테이너 외부와의 포트 매핑이 아니라
단지 80포트를 사용하고 있다는 메타데이터의 의미이다.
다른 개발자나 사용자가 사용 포트를 알 수 있게 하는 목적.
c3f279d17e0a 커밋 대상은 컨테이너 아이디 c3f279d17e0a 이다.
svendowideit/test:v4 생성하는 이미지 이름을 지정함

이번에는 commit 시에 환경변수를 추가하는 예제를 살펴보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# commit 전
docker ps
>> CONTAINER ID   IMAGE        COMMAND    ...   NAMES
>> c3f279d17e0a   ubuntu:22.04 /bin/bash  ...   desperate_dubinsky
>> 197387f1b436   ubuntu:22.04 /bin/bash  ...   focused_hamilton

# c3f279d17e0a 컨테이너의 환경변수를 조회
docker inspect -f "" c3f279d17e0a
>> [HOME=/ PATH=/usr/local/sbin:/usr/local/bin:...]

# commit 하면서 ENV에 DEBUG=true 추가
docker commit --change "ENV DEBUG=true" c3f279d17e0a  svendowideit/test:v3
>> f5283438590d

# commit을 통해 새로 만들어진 이미지의 환경변수를 조회
docker inspect -f "" f5283438590d
>> [HOME=/ PATH=/usr/local/sbin:/usr/local/bin:... DEBUG=true]

도커 스토리지 변경

도커를 다루다 보면 도커 이미지와 컨테이너가 저장되는 경로를 바꿔야 할 수도 있습니다. 도커 이미지는 기본적으로 /var/lib/docker 에 저장되지만, 만약 리눅스 서버의 / 디렉토리에 할당된 디스크의 크기가 작을 경우, 새로운 도커 이미지를 추가하거나 다른 패키지를 설치하는 등의 활동에 제약을 받을 수 있기 때문입니다.

도커 이미지와 컨테이너 저장 경로는 도커 데몬 설정 파일에서 지정해줄 수 있습니다. 설정 파일 적용시에는 도커 서비스를 꼭 재실행해줘야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 도커 저장 경로 확인
docker info | grep "Docker Root Dir"
>> /var/lib/docker

# 새로운 도커 저장 경로 디렉토리 생성
mkdir /data/docker

# 도커 설정 파일 수정 (파일이 없다면 생성하기)
vi /etc/docker/daemon.json

> {
> 	"data-root":"/data/docker" # 새로 생성한 도커 저장 디렉토리
> }

# 도커 서비스 재시작
systemctl stop docker
systemctl start docker
systemctl restart docker.socket

기존에 있던 이미지와 컨테이너 데이터가 있다면, 이들을 새로이 만들어진 도커 저장 디렉토리에 복사/이동 해주면 됩니다. 이 동작은 docker 서비스 중지(stop) 와 재시작(start) 사이에 해주는 것을 권장합니다.

1
2
3
4
5
6
7
8
9
# 도커 서비스 중지
systemctl stop docker

# 기존 도커 데이터 복사
cp -r /var/lib/docker /data/docker

# 도커 서비스 재시작
systemctl start docker
systemctl restart docker.socket

도커 서비스를 중지한 뒤 데이터를 복사하는 이유는 데이터 무결성 보장을 위함입니다.

(1) 파일 일관성 유지: 도커가 실행 중인 상태에서는 컨테이너가 계속 데이터를 읽고 쓰기 때문에, 복사시 파일의 일관성이 깨질 수 있습니다. 이를 방지하기 위해 도커를 중지하고 모든 파일이 고정된 상태에서 복사함으로써 일관성을 유지할 수 있습니다.

(2) 경쟁 조건 방지: 도커가 데이터를 읽고 쓰는 동안 데이터를 복사하면, 경쟁 조건(race condition)이 발생해 데이터가 불완전하거나 손상될 가능성을 높입니다. 도커를 중지하면 이러한 문제를 피할 수 있습니다.

(3) 잠금 문제 방지: 도커가 데이터를 사용하는 동안 파일 시스템에서 파일 잠금 문제가 발생하여 복사 과정에서 오류를 일으킬 수 있습니다. 도커를 중지하면 파일 잠금 문제가 발생하지 않습니다.

Reference

https://docs.docker.com https://domdom.tistory.com/589
https://yoo11052.tistory.com/144
https://dongle94.github.io/