답: 4.이미지 레이어는 이미지를 내려 받는 순간부터 삭제할 때 까지 로컬 컴퓨터의 이미지 레이어에 존재한다.
답: 2. 볼륨은 컨테이너와 독립적으로 존재하며 별도의 생애주기를 갖지만, 컨테이너에 연결할 수 있다.
// 볼륨이 사용된 멀티 스테이지 빌드 Dockerfile 스크립트의 일부
FROM diamol/dotnet-aspnet
WORKDIR /app
ENTRYPOINT ["dotnet", "ToDoList.dll"]
VOLUME /data
COPY --from=builder /out/ .
답: 이 인스트럭션을 사용해 만든 이미지로 컨테이너를 실행하면 자동으로 볼륨을 생성해 컨테이너에 연결해준다.
실행된 컨테이너에는 /data 디렉터리가 있는데 (윈도 컨테이너라면 C:\data) 이 디렉터리는 다른 디렉터리와 똑같이 사용할 수 있는데 이 디렉터리의 내용은 볼륨에 영구적으로 저장된다.
답: 도커 이미지에서 볼륨을 정의하면 컨테이너를 생성할 때마다 새로운 볼륨을 만든다. 하지만 컨테이너가 같은 볼륨을 공유하게 할 수도있다.
volumes-from 플래그를 적용하면 다른 컨테이너의 볼륨을 연결할 수 있다.
//이 컨테이너는 todo1 컨테이너의 볼륨을 공유한다. /data 디렉터리의 내용도 같다.
docker container run -d --name t3 --volumes-from todo1 diamol/ch06-todo-list
⭐️ 애플리케이션 컨테이너는 종종 자신만이 접근할 수 있는 파일을 필요로한다. 이러한 파일을 다른 컨테이너가 동시에 접근하게 허용하면 애플리케이션이 비정상적으로 동작할 수 있다. 볼륨은 컨테이너 간 파일공유보다는 업데이트 간 상태를 보존하기 위한 용도로 사용해야한다. 이미지에 정의하는 것 보다는 명식적으로 관리하는 편이 낫다.
볼륨에 이름을 붙여 생성하고 업데이트 시 다른 컨테이너로 옮겨 연결하면 된다.
참고
# 데이터를 저장할 볼륨도 생성한다
// 새로운 볼륨을 이름을 붙여 만든다. 지금은 그냥 빈 스토리지다.
docker volume create todo-list
# 볼륨을 연결해 v1 애플리케이션을 실행한다.
// -v 플래그를 사용해 새 컨테이너를 실행한다. 이 플래그는 컨테이너의 파일 시스템 경로 /data에 지정한 볼륨을 마운트 하라는 의미다.
docker container run -d -p 8011:80 -v todo-list:/data --name todo-v1 diamol/ch06-todo-list
답: 3 이미지에 볼륨이 정의돼 있더라도 이 정의가 무시되므로 새로운 볼륨이 생성되지 않는다.
참고
// 호스트 컴퓨터의 로컬 디렉터리를 컨테이너에 바인드 마운트로 연결해 보라. 파일 시스템 경로는 호스트 운영체제의 방식을 따라야한다.
// 본문의 명령을 그대로 복사해 사용할 수 있도록 경로를 환경 변수로 설정한다.
source="$(pwd)/databases" && target='/data'
// 바인드 마운트를 적용해 컨테이너를 실행. 호스트 컴퓨터의 data 디렉터리를 컨테이너 안에서 사용한다.
mkdir ./databases
docker container run --mount type=bind,source=$source,target=$target -d -p 8012:80 diamol/ch06-todo-list
// to-do 애플리케이션에 HTTP 요청을 보낸다. 이 요청을 받아 애플리케이션이 시작되며 데이터베이스 파일이 생성된다.
// 컨테이너 포트 80번을 호스트의 8012번 포트로 공개한다. curl 명령으로 컨테이너에 HTTP 요청을 보내면 애플리케이션이 시작되면서 data 에 데이터 베이스 파일이 생성된다.
curl http://localhost:8012
// 호스트 컴퓨터에 연결된 데렉터리에 데이터 베이스 파일이 생성된것을 확인하는 명령어 이다.
ls ./databases
docker-compose up
답: 4 이미 존재하는 대상 디렉터리에 마운트하면 마운트의 원본 디렉터리가 기존 디렉터리를 완전히 대체한다. 그래서 이미지에 포함돼 있던 원래 파일을 사용할 수 없다.
답: 3. 각각의 컨테이너를 일일히 옵션을 지정해가며 실행하는게 문제가 되기 때문에 옵션을 한데 모아놓은 도커 컴포즈 파일을 사용하는 것이다.
version: '3.7' 1️⃣
services:
todo-web: 2️⃣
image: diamol/ch06-todo-list
ports:
- "8020:80" 3️⃣
networks:
- app-net 4️⃣
networks: 5️⃣
app-net: // 서비스가 구성될 네트워크 이름
external: // nat 네트워크가 이미 존재하므로 새로 생성하지 말라는뜻
name: nat // app-net은 nat이라는 이름의 외부 네트워크로 연결됨
답: 3번 포트가 호스트 컴퓨터의 80번 포트로 자신의 8020 포트를 공개한다.
version: '3.7'
services:
accesslog:
image: diamol/ch04-access-log
networks:
- app-net
iotd:
image: diamol/ch04-image-of-the-day
ports:
- "80"
networks:
- app-net
image-gallery:
image: diamol/ch04-image-gallery
ports:
- "8010:80"
// 이 서비스는 다른 두 서비스에 의존한다는 사실을 기술했다.
depends_on:
- accesslog
- iotd
networks:
- app-net
networks:
app-net:
external:
name: nat
답: image-gallery 서비스를 시작하기 전에 accesslog와 iotd 서비스를 먼저 시작한다. 이것은 컴포즈 파일에 서비스 간의 의존관계를 설정하는 것이다.
참고
FROM diamol/dotnet-sdk AS builder
WORKDIR /src
COPY src/Numbers.Api/Numbers.Api.csproj .
RUN dotnet restore
COPY src/Numbers.Api/ .
RUN dotnet publish -c Release -o /out Numbers.Api.csproj
# app image
FROM diamol/dotnet-aspnet
ENTRYPOINT ["dotnet", "/app/Numbers.Api.dll"]
HEALTHCHECK CMD curl --fail http://localhost/health
WORKDIR /app
COPY --from=builder /out/ .%
답: 5 도커 엔진은 이상 상태에 있는 컨테이너를 재시작하거나 다른 컨테이너로 자동 교체하지 않는다.
version: "3.7"
services:
numbers-api:
image: diamol/ch08-numbers-api:v3
ports:
- "8087:80"
healthcheck:
interval: 5s
timeout: 1s
retries: 2
start_period: 5s
networks:
- app-net
numbers-web:
image: diamol/ch08-numbers-web:v3
restart: on-failure
environment:
- RngApi__Url=http://numbers-api/rng
ports:
- "8088:80"
healthcheck:
test: ["CMD", "dotnet", "Utilities.HttpCheck.dll", "-t", "150"]
interval: 5s
timeout: 1s
retries: 2
start_period: 10s
networks:
- app-net
networks:
app-net:
external:
name: nat
답: 스크래핑
답: 4 컴포즈가 사용하는 프로젝트 이름의 기본값을 바꿀 수 있으므로 이 프로젝트 이름을 바꾸는 방법으로 단일 도커 호스트에 같은 애플리케이션을 여러 벌 실행시킬 수 있다.
docker-compose -f ./todo-list/docker-compose.yml -p todo-test up -d
docker container ls
// 컨테이너의 공개된 포트를 알려주므로 컨테이너 이름으로 애플리케이션의 포트도 알 수 있다.
docker container port todo-test-todo-web-1 80
# 기존 컨테이너 모두 제거하기
docker container rm -f $(docker container ls -aq)
# 개발 환경용 설정으로 실행하기
docker-compose -f ./numbers/docker-compose.yml -f ./numbers/docker-compose-dev.yml -p numbers-dev up -d
# 테스트 환경용 설정으로 실행하기
docker-compose -f ./numbers/docker-compose.yml -f ./numbers/docker-compose-test.yml -p numbers-test up -d
# 인수 테스트 환경용 설정으로 실행하기
docker-compose -f ./numbers/docker-compose.yml -f ./numbers/docker-compose-uat.yml -p numbers-uat up -d
답: 3 : 이들은 모든 자신만의 네트워크 안에서 해당 환경의 API 컨테이너와만 통신할 수 있다. 이 때문에 세 환경의 애플리케이션은 서로 독립적이다.
개발 환경의 애플리케이션에 여러 번 무작위 숫자를 요청해 API가 버그를 일으키더라도 시스템 테스트 환경이나 사용자 인수 테스트 환경의 애플리케이션은 잘 동작한다.