Devin.KR

환경 변수·볼륨·포트

80분 안팎

학습 목표

환경별 설정과 지속 데이터의 역할을 분리합니다.

개념

환경을 바꾸려고 이미지를 다시 만들지 않습니다

테스트 안내판과 시연 안내판은 같은 프로그램을 사용하지만 표시 이름과 접속 포트, 저장 데이터는 달라야 합니다. 환경별로 JAR를 다시 빌드하면 테스트한 것과 시연한 것이 다른 산출물이 됩니다. 이 레슨은 한 이미지의 실행 입력으로 환경 변수를 전달하고, 호스트 포트 매핑과 볼륨을 따로 지정합니다. 코드 버전 변경과 환경 변경을 구분하여 각 변경의 영향과 복구 방법을 설명할 수 있게 합니다.

프로그램이 실제로 읽는 설정을 찾습니다

application.properties의 notice.name은 NOTICE_NAME에서, notice.data는 NOTICE_DATA에서, notice.log는 NOTICE_LOG에서 값을 받습니다. /identity는 표시 이름을 반환하고 /notices는 데이터 파일 내용을 읽습니다. ENV 지시에는 공통 경로만 두고 이름은 environments/test.env와 demo.env로 분리합니다. 변수 이름의 철자와 코드가 참조하는 설정이 일치해야 합니다. 존재하지 않는 임의 변수에 값을 넣어도 앱의 표시 이름은 바뀌지 않습니다.

환경 파일의 역할을 제한합니다

제공 파일에는 NOTICE_NAME=test-board 또는 demo-board처럼 공개 가능한 교육 설정만 있습니다. check-container.py는 각 줄을 읽어 docker run의 -e 인자로 전달합니다. 파일을 셸 source로 실행하지 않으며 명령 치환 기능을 기대하지 않습니다. 직접 실행할 때는 docker run --env-file을 사용할 수 있습니다. 환경 파일은 실행 프로세스 입력이지 이미지 파일이 아닙니다. 이번에는 비밀을 넣지 않고 비밀 전달과 회전은 다음 권한 모듈에서 다룹니다.

수신 주소는 어디에서 보이는지로 판단합니다

앞 모듈의 서버는 호스트의 127.0.0.1에 바인딩했습니다. 컨테이너 안의 127.0.0.1은 그 컨테이너 내부 루프백입니다. 외부의 포트 전달을 받으려면 여기서는 SERVER_ADDRESS=0.0.0.0으로 컨테이너 인터페이스에서 듣도록 설정합니다. 이것이 호스트의 모든 주소에 공개한다는 뜻은 아닙니다. 호스트의 공개 범위는 -p의 바인딩 주소로 별도로 정하며 이번 실습은 127.0.0.1만 사용합니다.

포트 매핑을 왼쪽과 오른쪽으로 읽습니다

-p 127.0.0.1:18081:8080은 호스트 루프백의 18081을 컨테이너의 8080으로 전달합니다. 다른 인스턴스는 호스트 18082를 사용할 수 있지만 컨테이너 내부 서버 포트는 둘 다 8080입니다. EXPOSE 8080만으로 이 매핑이 생기지 않습니다. 검사기는 127.0.0.1::8080으로 빈 호스트 포트를 자동 할당하고 inspect에서 실제 값을 읽습니다. 따라서 특정 포트 숫자를 성공 출력으로 고정하지 않습니다.

파일의 저장 장소를 명시합니다

NOTICE_DATA=/data/notice.txt는 컨테이너 안에서 보이는 경로입니다. named volume을 /data에 마운트하면 그 경로의 파일은 볼륨에 저장됩니다. 컨테이너 제거 뒤 같은 볼륨을 연결하면 내용을 다시 읽을 수 있습니다. 볼륨을 빼고 /data에 쓰면 컨테이너 쓰기 계층의 데이터가 되어 제거 때 잃습니다. 마운트 경로가 /wrong처럼 어긋나도 볼륨이 있다는 사실만으로 보존 목표를 충족하지 못합니다.

이름 붙인 볼륨과 bind mount를 구분합니다

named volume은 Docker가 관리하는 별도 저장 객체를 이름으로 연결합니다. bind mount는 지정 호스트 경로를 직접 연결하므로 호스트 폴더 구성과 소유권에 영향을 받습니다. 이번 예제는 named volume을 사용해 개인 경로 차이를 줄입니다. 이것만으로 장애에 대비한 백업이 되는 것은 아닙니다. 같은 daemon의 볼륨을 지우거나 저장 장치가 손상되면 데이터를 잃을 수 있으므로 재생성 보존과 백업 복원을 별도 기준으로 다룹니다.

두 환경의 데이터를 섞지 않습니다

검사기는 test와 demo에 서로 다른 볼륨을 만듭니다. test 파일을 kept-by-volume으로 바꾼 후 demo의 기본 안내 문장이 유지되는지 확인합니다. 같은 볼륨을 연결하면 환경 이름이 달라도 데이터가 공유될 수 있습니다. 공유가 목적이라면 별도 쓰기 충돌 계약이 필요하지만 이번 프로젝트의 요구는 격리입니다. 따라서 표시 이름 차이만으로 환경 분리를 선언하지 않고 마운트와 파일 응답도 비교합니다.

초기 데이터와 기존 데이터를 구분합니다

서비스는 notice.txt가 없을 때만 배포 연습 안내를 만듭니다. 이미 파일이 있으면 읽고 기본값으로 덮어쓰지 않습니다. 검사에서 파일 내용을 바꾸고 HTTP로 다시 읽은 뒤 컨테이너를 재생성하는 이유가 여기에 있습니다. 처음만 만드는 동작과 매번 덮어쓰는 동작은 첫 요청에서 같은 응답을 낼 수 있어 한 번의 검사로 구별되지 않습니다. 교육용 단일 프로세스 초기화이며 여러 작성자의 동시 갱신 계약은 제공하지 않습니다.

권한 실패를 기능 실패와 연결합니다

새 볼륨의 /data 소유자가 서비스 UID와 맞지 않으면 파일 생성이 실패할 수 있습니다. 검사기는 자기 볼륨에 한해 초기 chown을 수행하고 서비스는 10001로 실행합니다. /health는 파일을 읽지 않으므로 이 오류에서도 UP일 수 있습니다. /notices까지 요청해야 실제 데이터 경계를 확인합니다. 로그의 notice data unreadable과 하위 IOException을 살펴보고 경로·디렉터리 여부·소유권을 확인하며 모든 디렉터리에 쓰기 권한을 풀지 않습니다.

설정 변경은 새 실행에 적용합니다

환경 파일을 편집해도 이미 실행 중인 프로세스의 시작 환경은 자동으로 바뀌지 않습니다. 파일 변경 뒤 컨테이너를 새로 생성하고 /identity로 실제 읽은 값을 확인합니다. 이미지 ID는 그대로라 코드 변경 없이 설정만 바뀌었다고 설명할 수 있습니다. 반대로 새 이미지를 만들면서 표시 이름이 우연히 바뀌었다면 어느 입력이 원인이었는지 구분하기 어렵습니다. 설정 파일 내용과 새 컨테이너의 관측값을 나란히 기록합니다.

이름이 중복된 시작 코드를 수정합니다

이번 starter는 demo.env에도 test-board를 넣어 demo 표시 이름 검사가 실패합니다. demo-board로 고친 뒤 통합 검사를 실행합니다. 두 호스트 포트는 다르고 이미지 ID는 같아야 하며 /identity의 이름만 환경에 맞게 달라야 합니다. 이어 test 데이터 변경, demo 격리, test 재생성 후 유지 검사가 통과하는지 봅니다. 앱 코드를 환경마다 바꾸는 방식은 이 레슨이 요구하는 하나의 산출물 정책과 맞지 않습니다.

제출 기록에는 호스트 주소와 할당 포트, 컨테이너 포트, 변수 이름, 볼륨 이름과 마운트 경로를 따로 적습니다. 검사 종료 후 임시 볼륨은 정리되므로 이 기록은 사용 중인 환경 목록이 아니라 실험 증거입니다. 영속 환경에서는 데이터 보존 정책을 먼저 정한 뒤 정리합니다. 환경 변수의 셸 전달 방식은 서재의 env 장에서 더 읽고 여기서는 실제 앱 응답으로 적용 여부를 판단합니다.

포트 publish와 환경 입력의 옵션은 공식 container run 문서에서 확인할 수 있습니다. 본문 명세의 값은 문서 예제가 아니라 개인 실습에서 관측한 값으로 채웁니다.

따라하기

설정 차이 수정

demo.env를 NOTICE_NAME=demo-board로 고칩니다. test는 test-board를 유지하고 설정이 Dockerfile에 굳지 않았는지 봅니다.

cat environments/test.env
cat environments/demo.env

포트 매핑 관측

검사는 두 임의 포트를 배정합니다. distinct host ports와 both health responses, 환경별 display name 항목을 확인합니다.

bash check.sh

볼륨 증거 확인

성공 명세에서 두 환경의 서로 다른 volume과 configSha256을 확인합니다. 정리된 검사 자원이므로 지금 접속 가능한 포트라고 해석하지 않습니다.

python3 -m json.tool release.json

재생성 판정

service reads changed data file, demo volume isolated, data preserved after recreation을 확인합니다. 두 번째 검사도 자체 새 볼륨에서 같은 절차를 수행하므로 이전 검사 볼륨을 재사용한 증거가 아닙니다.

bash check.sh

확인 문제

실습

demo.env의 표시 이름을 고치고 서로 다른 호스트 포트·별도 볼륨·재생성 보존을 확인합니다. 검사 코드와 기대값은 수정하지 않습니다. bash check.sh가 해당 결함을 거부하고 solution은 전체 HTTP·데이터·명세 검사를 통과해야 합니다. 실행 도구가 없는 환경에서는 external 검증 대기로 남깁니다.

시작 코드·테스트 내려받기

실행 명령

bash check.sh

기대 결과

개인 Docker 환경에서 모든 PASS 항목과 RESULT: 0 failure(s). 실제 imageDigest를 기록한 release.json 생성.

모범 답안모범 답안 내려받기

더 읽기

면접 질문

  • 환경마다 달라지는 설정을 주입하는 방법을 설명합니다.