본문 바로가기

복사금지 블로그 짜증나서 만든 개발문서

docker compose down을 stop 대신 쓰면 무엇이 사라질까

반응형

환경  Docker Compose v2 (docker compose)

잠깐 내려두려고 down 을 쳤다가, 다시 올린 컨테이너가 빈손으로 뜨는 일이 있다. stop 과 down 은 세기의 차이가 아니라 지우는 범위의 차이다. 무엇이 남고 무엇이 사라지는지 한 번에 정리해 두면 급할 때 손이 헷갈리지 않는다.

두 명령이 손대는 범위가 다르다

stop 은 컨테이너를 멈추기만 한다. 컨테이너는 목록에 그대로 남고, start 로 다시 켜면 멈추기 직전 상태에서 이어진다. down 은 멈춘 다음 치운다. 치우는 대상은 컨테이너와 compose 가 만든 네트워크다.
볼륨은 down 만으로는 안 지워진다. -v 를 붙여야 compose 파일의 volumes 에 이름을 적어 둔 볼륨과, 컨테이너에 딸린 익명 볼륨까지 지운다. 그래서 "-v 를 안 붙였으니 데이터는 안전하다"는 말은 절반만 맞다. 볼륨이 안전한 것이지 컨테이너가 안전한 게 아니다.
정리하면 이렇게 갈린다.

지워지는가                   stop    down    down -v
---------------------------  ------  ------  -------
컨테이너                     남음    삭제    삭제
컨테이너 안에 쓴 파일        남음    사라짐  사라짐
compose 가 만든 네트워크     남음    삭제    삭제
이름 붙인 볼륨               남음    남음    삭제
익명 볼륨                    남음    남음    삭제
바인드 마운트한 호스트 폴더  그대로  그대로  그대로
다시 올리는 명령             start   up      up

멈출 것인지 치울 것인지에서 갈린다

down 은 stop 의 강한 버전이 아니다. 종류가 다른 명령이다.

컨테이너를 지우면 그 안에 쓴 파일도 같이 지워진다

컨테이너가 돌면서 만든 파일은 대부분 그 컨테이너의 쓰기 레이어에 쌓인다. 이 레이어는 컨테이너마다 하나씩 붙어 있고, 컨테이너가 사라지면 같이 사라진다. 볼륨이나 바인드 마운트로 밖에 빼 둔 경로만 남는다.
업로드 폴더를 호스트에 마운트해 뒀다면 그건 살아남는다. 반면 애플리케이션이 컨테이너 안 /var/log 나 /tmp 에 쌓아 둔 것, 컨테이너에 들어가 손으로 고친 설정 파일, DB 컨테이너를 볼륨 없이 띄우고 넣어 둔 초기 데이터는 down 한 번에 없어진다.
up 으로 다시 올려도 돌아오지 않는다. up 은 지워진 자리에 새 컨테이너를 만드는 것이지 아까 그 컨테이너를 깨우는 게 아니다. 이름과 설정만 같을 뿐 다른 컨테이너다.
그러니 down 을 치기 전에 볼륨 밖에 뭐가 있는지부터 본다.

# compose 파일이 선언한 볼륨 이름
docker compose config --volumes

# 실제로 컨테이너에 붙어 있는 마운트
docker inspect -f '{{range .Mounts}}{{.Type}}  {{.Source}} -> {{.Destination}}{{println}}{{end}}' <컨테이너>

여기에 안 잡히는 경로는 컨테이너와 운명을 같이한다

네트워크가 사라지면 밖에서 붙어 있던 쪽이 먼저 끊긴다

down 은 그 프로젝트의 기본 네트워크도 지운다. compose 안에서만 도는 구성이라면 티가 안 난다. 어차피 다음 up 에서 같은 이름으로 다시 만들어진다.
문제는 섞어 쓰는 구성이다. DB 는 compose 로 띄우고, 작업용 컨테이너는 docker run 으로 띄워 같은 네트워크에 붙여 놓은 경우. down 하는 순간 그 네트워크가 없어지면서 밖에 있던 컨테이너가 이름으로 DB 를 못 찾는다. 정작 죽는 쪽은 내가 건드리지 않은 컨테이너다.
밖에서 만들어 둔 네트워크는 down 이 손대지 않는다. compose 파일에서 external 로 참조만 하면 양쪽이 같은 네트워크를 공유하면서도 down 에 딸려가지 않는다.

# 지금 어떤 네트워크에 누가 붙어 있는지
docker network inspect <프로젝트>_default \
  -f '{{range .Containers}}{{.Name}}{{println}}{{end}}'

# 밖에서 만들어 두고 compose 는 참조만 하게
docker network create shared-net

compose 밖 컨테이너가 하나라도 붙어 있으면 확인하고 내린다

설정을 고쳤는데 restart 로는 안 붙는다

compose.yaml 을 고친 뒤 restart 를 치는 경우가 많다. 그런데 restart 는 컨테이너를 껐다 켜기만 한다. 이미 만들어진 컨테이너의 설정은 그대로라 바꾼 내용이 반영되지 않는다. 포트를 바꿨는데 예전 포트로 계속 뜨는 게 대표적이다.
반영하려면 up 을 다시 친다. up 은 설정이나 이미지가 바뀐 서비스만 골라 컨테이너를 새로 만든다. 이때 마운트된 볼륨은 유지된다. 바뀐 게 없는 서비스는 건드리지 않고 그대로 둔다.
그래서 설정을 고쳤다는 이유로 down 까지 갈 일은 거의 없다. up 이 필요한 것만 새로 만들고, 그래도 안 바뀌면 그 서비스만 골라 강제로 다시 만들면 된다.

docker compose up -d              # 바뀐 서비스만 새로 만든다
docker compose up -d --build api  # 이미지부터 다시 굽는다
docker compose up -d --force-recreate api

restart 자리에 up -d 를 넣는다

restart 는 설정을 다시 읽지 않는다. 다시 읽게 하는 건 up 이다.

그래서 언제 어느 쪽을 쓰나

잠깐 내려두는 거라면 stop 이다. 노트북을 닫기 전, 포트를 다른 작업에 잠깐 넘길 때. 컨테이너가 그대로 있으니 start 로 몇 초면 돌아오고, 안에 쌓인 것도 그대로다.
구성을 정리할 때는 down 이다. 서비스 이름을 바꿨거나, compose 파일에서 지운 서비스의 컨테이너가 계속 살아 있거나, 네트워크 설정을 바꿔야 할 때. 이때는 --remove-orphans 를 같이 붙여 목록에서 사라진 서비스의 잔여 컨테이너까지 정리한다.
-v 는 데이터를 버리기로 마음먹었을 때만 쓴다. 로컬 DB 를 초기 상태로 되돌리는 정도가 적당하다. 손에 익혀 두면 급할 때 그대로 나가니, 이 옵션은 매번 볼륨 이름을 확인하고 붙이는 습관을 들이는 편이 낫다.

docker compose stop               # 잠깐 멈춤
docker compose start              # 그대로 재개

docker compose down --remove-orphans   # 구성 정리
docker volume ls                       # -v 전에 지워질 이름부터 확인
docker compose down -v                 # 데이터까지 버릴 때만

-v 는 확인 다음에 붙인다

조치 후 확인할 것

  • stop 으로 내렸으면 docker compose ps -a 에 컨테이너가 그대로 보여야 한다. 목록에서 사라졌다면 stop 이 아니라 down 이 돌아간 것이다.
  • down 전에 docker compose config --volumes 와 docker inspect 로 볼륨 밖에 남은 데이터가 있는지 본다.
  • -v 를 붙이기 전에 docker volume ls 로 지워질 볼륨 이름을 눈으로 확인한다.
  • 설정을 고쳤으면 restart 말고 up -d 로 올리고, docker compose ps 에서 생성 시각이 갱신됐는지 확인한다.

stop 과 down 은 세기의 차이가 아니라 종류의 차이다. 멈출 것인지 치울 것인지만 먼저 정하면 어느 쪽을 칠지는 저절로 갈린다.

반응형