빌드노트
같은 태그로 다시 빌드했는데 Docker restart 뒤에도 옛 코드다
같은 태그로 이미지를 다시 빌드한 뒤 restart해도 옛 코드가 보이면, 태그의 현재 이미지 ID와 기존 컨테이너의 이미지 ID를 비교한다. v1/v2 HTTP 본문을 실제로 대조해 재시작과 새 컨테이너 생성의 차이, 재생성을 선택할 조건을 설명한다.
같은 태그로 Docker 이미지를 다시 빌드했는데, 기존 컨테이너를 restart해도 옛 코드가 실행될 수 있다. 태그가 새 이미지를 가리키게 된 것과 기존 컨테이너의 이미지가 바뀌는 것은 별개이기 때문이다. 새 이미지가 준비됐는지 확인한 다음, 컨테이너가 생성될 때 사용한 이미지 ID와 비교해야 한다.
Docker의 restart 명령 (새 탭에서 열림)은 기존 컨테이너를 재시작한다. 이미지는 생성 후 바뀌지 않으며 (새 탭에서 열림), 내용이 다른 빌드 결과는 새 이미지다. 같은 태그를 붙여도 이미 만들어진 컨테이너까지 새 이미지로 교체하지는 않는다.
태그 문자열 대신 두 이미지 ID를 비교한다
Docker CLI가 연결되는 데몬에 확인할 이미지와 컨테이너가 있어야 한다. 다음은 PowerShell 명령이다. 첫 두 줄을 자신이 빌드한 태그와 확인할 컨테이너 이름으로 바꾼다. 빌드한 곳과 다른 Docker context나 원격 서버를 조회하면 이번 빌드와 비교할 수 없다.
$tag = 'my-app:local'
$container = 'my-app'
docker image inspect --format 'tag-current={{.Id}}' $tag
docker container inspect --format 'container-image={{.Image}}' $container
docker container inspect --format 'created-from={{.Config.Image}}' $container
tag-current는 그 데몬에서 태그가 현재 가리키는 로컬 이미지 ID이고, container-image는 컨테이너가 사용한 이미지 ID다. created-from은 생성할 때 지정한 이미지 참조 문자열이다. 이미지 inspect (새 탭에서 열림), 컨테이너 inspect (새 탭에서 열림), Config.Image 조회 예시 (새 탭에서 열림)에서 조회 방법을 확인할 수 있다.
created-from에 방금 빌드한 태그가 나와도 새 이미지 적용의 증거가 되지 않는다. 같은 데몬·단일 플랫폼에서 두 이미지 ID가 다른지가 이 문제의 확인 지점이다. 여기서 비교하는 것은 컨테이너 자체의 .Id가 아니라 컨테이너의 .Image다.
조회가 실패했다면 빈 출력을 ID로 비교하지 않는다. 태그가 그 데몬에 실제로 적재됐는지, 컨테이너 이름이 맞는지부터 확인한다. docker image inspect는 레지스트리의 최신 태그를 조회하거나 이미지를 내려받는 명령이 아니다.
v2를 빌드한 뒤 재시작해도 본문은 v1이었다
이를 확인하려고 운영 앱과 별개인 작은 HTTP 이미지를 만들었다. BusyBox 1.37.0 위에 index.html을 /www/index.html로 복사하고 httpd로 제공했다. 첫 빌드의 파일 내용은 v1과 줄바꿈, 두 번째는 v2와 줄바꿈이다. 두 빌드는 같은 실습 전용 :current 태그를 사용했다. 마운트는 없었고 호스트 접속 주소는 127.0.0.1로 제한했다.
v1 이미지에서 만든 첫 컨테이너는 HTTP 200과 v1을 반환했다. 같은 태그로 v2를 빌드하자 태그의 이미지 ID는 바뀌었지만 기존 컨테이너의 이미지 ID와 응답은 그대로였다. 이어 기존 컨테이너를 종료 대기 제한 2초로 재시작했다. 컨테이너 ID는 유지되고 시작 시각은 바뀌었지만 본문은 여전히 v1이었다.
재시작 직후 위 조회 명령을 실습 자원에 적용한 출력이다. 읽기 쉽게 이미지 ID는 앞 12자리만 남겼다.
tag-current=sha256:d7b31369d1b7…
container-image=sha256:74280cd2de9d…
created-from=localhost/restart-image-lab-16952b3c78a9:current
그다음 같은 태그로 새 컨테이너를 생성했다. 새 컨테이너의 이미지 ID는 tag-current와 같았고, HTTP 200과 v2를 반환했다. 기존 컨테이너와 새 컨테이너의 created-from 문자열은 같았다. 태그 이름만 보면 놓칠 차이가 이미지 ID와 본문에 함께 나타났다.
이는 Windows의 Docker Desktop 4.92.0, Docker Engine 29.8.0, Linux/amd64 컨테이너와 PowerShell 7.6.6에서 따로 실행한 관찰이다. 실제 앱 장애나 운영 재배포를 재현한 결과는 아니다.
ID가 다르면 재시작 대신 재생성을 선택한다
태그의 현재 이미지가 의도한 새 빌드이고 기존 컨테이너의 이미지 ID가 다르다면, 새 이미지를 사용하도록 컨테이너를 재생성해야 한다. docker run (새 탭에서 열림)은 이미지에서 새 컨테이너를 만드는 명령이다. 기존 실행 옵션을 확인하지 않은 채 이름만 바꿔 실행하면 원래 서비스와 같은 구성이라고 볼 수 없다.
Compose를 쓴다면 up 문서 (새 탭에서 열림)가 이미지나 설정 변경을 반영하는 재생성 동작을 설명한다. --build는 시작 전 빌드, --no-recreate는 기존 컨테이너의 재생성을 막는 옵션이다. 새 이미지 준비와 컨테이너 교체가 자신의 배포 절차에 모두 포함돼 있는지 확인한다. 이 실험에서 Compose 재배포는 실행하지 않았다.
두 이미지 ID가 이미 같다면 여기서 관찰한 이미지 참조 불일치는 확인되지 않은 것이다. 빌드 결과에 수정한 파일이 들어갔는지, 실제 요청이 그 컨테이너에 도달하는지로 조사를 옮긴다. 같은 ID라는 사실만으로 실행 중 코드까지 올바르다고 결론 내릴 수는 없다.
이번 실험에는 저장 데이터나 볼륨이 없었다. 컨테이너 재생성 시 데이터 보존, 운영 서비스의 실행 옵션 복원, 무중단 교체는 검증하지 않았다. 재생성을 결정했다면 실제 교체 전에 데이터 저장 위치와 필요한 실행 구성을 별도로 확인해야 한다.