빌드노트
docker exec에서 export했는데 앱 설정은 그대로다
실행 중인 컨테이너에서 일반 exec, exec -e, 셸의 export를 비교한다. 새 진단 프로세스의 환경과 기존 앱의 설정을 구분하고, 시작 시 읽는 값은 배포 정의에 넣어야 하는 이유를 실제 관찰로 설명한다.
docker exec로 들어간 셸에서 export한 값은 보이는데 앱 설정은 그대로일 수 있다. export는 그 셸과 이후 그 셸이 시작하는 자식에게 적용된다. 이미 실행 중인 앱의 환경을 바꾸지는 않는다. 앱이 시작할 때 환경변수를 읽는다면, 값을 넣을 곳은 exec 셸이 아니라 앱을 시작하는 배포 설정이다.
Docker의 exec 문서 (새 탭에서 열림)에 따르면 exec는 실행 중인 컨테이너에 새 명령을 시작한다. 새 exec의 기본 환경은 컨테이너 생성 시 정한 값이고, exec -e는 그 실행에만 값을 추가하거나 덮어쓴다. 같은 컨테이너의 모든 프로세스가 환경변수 한 벌을 공유하는 구조가 아니다.
새 exec의 값과 앱의 값을 구분한다
먼저 실행 중인 대상 컨테이너에서 새 명령이 받는 값부터 확인한다. 아래는 PowerShell 7용 명령이며, $container에는 확인할 컨테이너 이름이나 ID를 넣는다. 예를 들어 $container = '내_컨테이너_이름'처럼 지정한다. 컨테이너가 실행 중이고 내부에 sh와 printenv가 있어야 한다. 이 예제의 LAB_MODE는 비밀이 아닌 합성 변수다. 자기 환경에서는 확인하려는 공개 설정 키 하나로 바꾼다.
docker exec $container printenv LAB_MODE
docker exec -e LAB_MODE=exec-only $container printenv LAB_MODE
docker exec $container printenv LAB_MODE
LAB_MODE=container-default로 시작한 별도 컨테이너에서 얻은 실제 출력이다.
container-default
exec-only
container-default
두 번째 명령의 printenv만 다른 값을 받았다. 세 번째 명령이 원래 값으로 돌아온 것은 변경이 취소됐기 때문이 아니다. -e가 두 번째 exec의 환경만 바꿨기 때문이다. 첫 번째와 세 번째 출력은 새로 시작한 printenv의 값이며, 실행 중인 앱이 사용 중인 설정을 조회한 결과는 아니다.
변수가 없는 컨테이너에서는 일반 exec의 printenv LAB_MODE가 아무것도 출력하지 않고 종료 코드 1을 반환할 수 있다. PowerShell에서는 각 명령 직후 $LASTEXITCODE로 확인한다. 컨테이너가 멈췄거나 실행 파일을 찾지 못했다는 오류가 있다면 그 문제부터 해결한다. 빈 출력만 보고 앱 설정도 비었다고 판단하지 않는다.
export도 같은 대상에서 비교했다. 작은따옴표는 $LAB_MODE를 PowerShell에서 치환하지 않고 컨테이너의 셸로 전달한다.
docker exec $container sh -c 'export LAB_MODE=shell-only; echo shell=$LAB_MODE; printenv LAB_MODE'
docker exec $container printenv LAB_MODE
첫 명령에서 셸은 shell=shell-only, 그 셸이 시작한 printenv는 shell-only를 출력했다. 다음 exec는 다시 container-default였다. export한 셸의 자식에게 값이 전달된 것과, 컨테이너의 생성 설정이 바뀐 것은 다르다. 별도로 연 exec는 그 셸의 자식으로 시작하지 않는다.
처음부터 실행 중이던 프로세스는 그대로였다
새 exec의 결과와 구별하기 위해, 같은 격리 실험에서 컨테이너 시작 때부터 기다리던 BusyBox 셸 PID 1도 자기 값을 다시 출력하게 했다. 시작 때는 pid1-start=container-default,pid=1, exec와 export 비교 뒤에는 pid1-now=container-default,pid=1이 나왔다. 두 번째 값은 과거 시작 로그를 다시 본 것이 아니라 기존 셸이 새로 읽어 출력한 값이다.
전후 호스트 PID와 컨테이너 시작 시각은 같았고 재시작 횟수는 0이었다. 컨테이너 생성 설정의 해당 항목도 LAB_MODE=container-default를 유지했다. 이 관찰은 exec의 환경 변경이 기존 프로세스나 생성 설정에 전파되지 않았다는 설명과 일치한다. PID 1의 재출력은 실험용으로 넣은 동작이며, 실제 앱에 같은 동작이 있다고 가정해서는 안 된다.
자기 앱에서는 컨테이너의 Config.Env가 생성 설정이고, exec printenv는 새 진단 프로세스의 환경이라는 점을 구분한다. 앱이 실제로 사용한 값은 앱의 진단 출력이나 설정을 읽는 코드 경로로 확인한다. 시작 스크립트나 앱 자체에서 값을 바꾸는 경우도 있으므로, 생성 설정만 보고 현재 앱의 내부 설정까지 확정할 수는 없다.
시작할 때 읽는 값은 시작 경로에 넣는다
한 번 실행할 진단 명령에만 다른 값이 필요하면 docker exec -e를 쓴다. 같은 셸이 시작할 여러 명령에 전달하려면 그 셸에서 export한다. 앱이 시작 시 읽는 설정을 바꾸려면 배포 정의의 환경변수를 수정하고 그 정의로 새 컨테이너를 시작해야 한다. exec에서 export한 뒤 기존 컨테이너를 재시작하는 것만으로 그 값이 생성 설정에 저장되지는 않는다.
새 시작 프로세스에 값을 주는 위치는 다음처럼 docker run의 -e다. 아래는 앱 교체 명령이 아니라 전달 위치만 확인하는 일회성 예제다. 로컬에 busybox:1.37.0 이미지가 있어야 하며, 없으면 --pull=never 때문에 실패한다. 네트워크를 끈 새 컨테이너가 값을 출력하고 종료하면 자동 삭제된다.
docker run --rm --pull=never --network none -e LAB_MODE=startup-green busybox:1.37.0 printenv LAB_MODE
실제 출력은 startup-green이었다. Docker의 run 환경변수 옵션 (새 탭에서 열림)은 새 컨테이너에 값을 지정하거나 이미지의 기본값을 덮는다. 자기 앱에는 실제 설정 키와 값을 앱의 시작 정의에 넣는다. 시작 경로까지 값이 맞는데 앱 동작만 다르면 변수 이름과 앱의 설정 우선순위를 확인한다. 재시작 없이 바꾸려면 앱이 지원하는 설정 갱신 경로가 필요하다.
이번 확인은 PowerShell 7.6.6, Docker CLI·Engine 29.8.0, Linux/amd64, BusyBox 1.37.0에서 합성 값으로 실행했다. 실제 앱의 설정 캐시·파일 재로딩·프레임워크 우선순위와 운영 앱 재시작은 검증하지 않았다.