소개
보고서 서비스는 설정을 읽고 문서를 작성해야 하지만 현재 설정 마운트는 쓰기도 허용합니다. 유지보수 담당자로서 보고서 생성을 유지하면서 불필요한 접근을 줄입니다.
먼저 정상 보고서를 생성한 다음 입력 마운트를 보호하고 보고서 컨테이너만 다시 생성합니다. 기본적인 터미널 사용 경험이면 충분하며 Docker, 마운트 문법과 편집 방법은 사용 전에 설명합니다.
정상 보고서 생성
이 단계에서는 권한을 변경하기 전에 서비스의 정상 업무를 실행합니다. Harbor Books는 작은 서비스로 주문을 합산하고 문서를 생성합니다. 모든 고객과 숫자는 합성 교육 데이터입니다.
Maintenance 터미널을 사용합니다. Docker 관리 접근 권한을 가진 Linux 호스트 유지보수 역할입니다. Docker는 컨테이너에서 애플리케이션 프로세스를 시작합니다. 각 컨테이너는 자체 파일 시스템과 프로세스 목록을 보지만 호스트 커널을 공유합니다. 컨테이너는 별도의 VM이 아닙니다. 관리 대상은 report-renderer와 /home/labex/project/report-desk의 파일뿐입니다.
터미널은 해당 디렉터리에서 시작합니다. pwd는 현재 디렉터리를 출력합니다.
pwd
/home/labex/project/report-desk가 보여야 합니다. 다른 곳으로 이동했다면 cd /home/labex/project/report-desk로 돌아갑니다.
애플리케이션은 포트 8090에서 수신합니다. 포트는 서비스를 식별합니다. 여기서 localhost는 유지보수 호스트이며 Docker가 이 포트를 컨테이너로 전달합니다. curl은 HTTP 요청을 보내고 -X POST는 작업 요청을 선택하며 -fsS는 성공 출력을 간결하게 유지하면서 오류를 표시합니다. 기준 문서를 요청합니다.
curl -fsS -X POST http://localhost:8090/render/baseline
{"saved": "/output/baseline.json", "total": 37, "uid": 0}
서비스가 입력을 읽고 실제 파일을 저장했습니다. cat은 파일 내용을 표시합니다. 호스트에서는 컨테이너의 /output이 로컬 output 디렉터리로 보입니다.
cat output/baseline.json
Report for Harbor Books: 37 orders를 찾습니다. 다른 필드는 입력 식별 정보와 실행 중인 서비스 인스턴스를 기록합니다. Document Desk를 열고 새로 고치면 Stored documents 아래에 baseline.json이 나타납니다. 이 페이지는 실제 파일 목록이며 권한의 안전성을 인증하지는 않습니다.
입력 실행 선언 보호
이 단계에서는 입력과 출력 경로를 연결하고 불필요한 쓰기를 시연한 뒤 실행 선언을 편집합니다. 바인드 마운트는 호스트 디렉터리를 컨테이너 내부 경로에 연결합니다. 명시적으로 제한하지 않으면 쓰기가 가능합니다.
cat launch.sh로 준비된 Bash 실행 스크립트를 확인합니다.
cat launch.sh
역슬래시는 명령을 다음 줄로 이어 줍니다. sudo는 호스트 관리자 권한으로 Docker를 관리하지만 애플리케이션 사용자를 결정하지는 않습니다. docker run -d는 컨테이너를 백그라운드로 시작하고 --name은 이름을 지정하며 --user 0:0은 사용자/그룹 ID를 선택합니다. -p 8090:8090은 호스트 포트를 컨테이너 포트로 전달합니다. 마지막 인수는 준비된 애플리케이션 이미지 c12-renderer:1입니다.
각 --mount의 필드는 쉼표로 구분됩니다. type=bind는 호스트 경로를 연결하며 src는 호스트 경로, dst는 컨테이너 경로입니다.
| 호스트 디렉터리 | 컨테이너 디렉터리 | 필요한 접근 |
|---|---|---|
report-desk/config |
/config |
배치와 템플릿 읽기 |
report-desk/output |
/output |
생성한 문서 쓰기 |
설정에는 업무 데이터가 없는 일회용 샘플 probe.txt가 있습니다. docker exec는 지정한 실행 중 컨테이너 안에서 명령을 실행합니다. touch는 샘플의 타임스탬프를 갱신합니다. 이는 의도적으로 불필요한 애플리케이션 접근을 보여 줍니다.
sudo docker exec report-renderer touch /config/probe.txt
출력이 없으면 성공입니다. 배치나 템플릿을 손상하지 않고 설정 마운트에 쓰기가 가능함을 확인했습니다. 호스트 실행 선언을 바꾸면 Docker가 다음에 생성할 컨테이너가 달라집니다. 현재 컨테이너 내부 파일을 편집해도 마운트 모드는 바뀌지 않습니다.
터미널 편집기 nano로 선언을 수정합니다.
nano launch.sh
방향키로 이동합니다. dst=/config가 있는 줄에서 /config 바로 뒤, 공백과 역슬래시 앞에 ,readonly를 추가합니다. /output은 쓰기 가능한 상태로 유지합니다. Ctrl+O, Enter로 저장하고 Ctrl+X로 종료합니다. 설정 마운트 줄은 다음과 같습니다.
--mount type=bind,src=/home/labex/project/report-desk/config,dst=/config,readonly \
cat launch.sh를 다시 표시해 쉼표나 역슬래시 누락을 찾습니다. 오타는 nano launch.sh를 다시 열어 고칩니다. 실행 중인 컨테이너는 아직 이전 마운트를 사용하며 다음 단계에서 교체합니다.
마운트 경계 적용 및 테스트
이 단계에서는 보고서 컨테이너만 교체하고 입력 쓰기를 차단하면서 출력이 작동함을 입증합니다. 실행 스크립트가 바뀌어도 Docker가 기존 컨테이너를 자동 갱신하지는 않습니다.
docker rm -f는 지정한 컨테이너를 중지하고 제거합니다. 바인드 마운트된 호스트 디렉터리는 남습니다. bash launch.sh는 편집한 선언을 실행합니다.
sudo docker rm -f report-renderer
bash launch.sh
두 번째 명령은 새 컨테이너 ID를 출력합니다. 시작할 때까지 잠시 기다립니다. 문법 또는 마운트 오류가 나면 nano launch.sh로 해당 줄을 고치고 같은 제거 명령으로 새 report-renderer를 제거한 뒤 스크립트를 다시 실행합니다. 호스트 데이터 디렉터리는 삭제하지 마세요.
docker inspect는 실제 컨테이너 설정을 읽습니다. --format은 필드를 선택합니다. 셸이 중괄호를 그대로 전달하도록 작은따옴표를 유지합니다.
sudo docker inspect report-renderer --format '{{json .Mounts}}'
"Destination":"/config"에 "RW":false, /output에 "RW":true가 있는지 찾습니다. RW는 읽기/쓰기를 뜻합니다. 같은 일회용 샘플로 실제 경계를 확인합니다.
sudo docker exec report-renderer touch /config/probe.txt
touch: /config/probe.txt: Read-only file system
0이 아닌 종료는 예상된 결과입니다. 터미널은 계속 사용할 수 있으므로 다음 명령을 실행합니다. 연결 오류나 컨테이너 없음은 다른 문제이며 실행 스크립트를 고치거나 다시 실행해야 합니다.
다시 생성된 서비스에 새 문서를 요청합니다.
curl -fsS -X POST http://localhost:8090/render/final
{"saved": "/output/final.json", "total": 37, "uid": 0}
cat output/final.json
문서에는 여전히 Report for Harbor Books: 37 orders가 있습니다. Document Desk를 새로 고쳐 final.json을 확인합니다. 서비스는 입력을 읽고 출력을 쓰면서 설정 마운트의 쓰기를 거부합니다. 아직 root로 실행 중이며 다음 독립 실습에서 이 별도의 권한을 다룹니다.
요약
실제 보고서를 생성하고 호스트와 컨테이너 경로를 연결한 뒤 입력 마운트를 읽기 전용으로 바꾸고 서비스를 다시 생성했습니다. 실제 마운트 검사와 쓰기 거부로 보호를 확인했고 새 보고서로 정상 출력이 유지됨을 확인했습니다.



