본문 바로가기
빌드노트 검색

빌드노트

프로필을 켜지 않았는데 지정한 Compose 서비스가 실행된다

Compose 서비스에 profiles: [tools]를 넣었는데 docker compose up job-a로 실행하니 컨테이너가 생겼다면, 서비스 이름을 직접 지정했는지부터 본다. 프로필을 활성화하지 않아도 명시한 서비스는 실행된다.

Compose 서비스에 profiles: [tools]를 넣었는데 docker compose up job-a로 실행하니 컨테이너가 생겼다면, 서비스 이름을 직접 지정했는지부터 본다. 프로필을 활성화하지 않아도 명시한 서비스는 실행된다. profiles는 평소 실행할 서비스 집합을 고르는 설정이며, 그 서비스를 직접 실행하는 명령을 막지는 않는다. Docker의 프로필 실행 설명 (새 탭에서 열림)

그렇다고 job-a와 같은 프로필에 속한 job-b까지 모두 시작되는 것은 아니다. 이번 비교에서는 이름을 지정한 job-a만 실행됐고, depends_on을 추가했을 때 해당 의존 서비스가 함께 실행됐다. 프로필 이름과 명령 끝의 서비스 이름을 따로 읽어야 실행 범위를 알 수 있다.

이미 끝난 작업도 목록에 포함한다

먼저 문제가 난 명령과 같은 Compose 파일·프로젝트를 조회한다. 다음은 PowerShell에서 사용할 명령이다. 원래 실행에 -f, -p, --env-file을 썼다면 docker compose 뒤에 같은 옵션을 붙인다. job-a는 실제 조사할 서비스 이름으로 바꾼다. 첫 줄은 생성된 컨테이너와 종료 상태를, 둘째 줄은 해당 작업의 출력을 확인한다.

docker compose --profile "*" ps -a --format '{{.Service}} {{.State}} {{.ExitCode}}'
docker compose --profile "*" logs --no-color --tail 20 job-a

여기서 --profile "*"는 모든 프로필을 포함해 조회하기 위한 옵션이다. ps와 logs는 컨테이너를 시작하지 않는다. ps는 기본적으로 실행 중인 컨테이너만 보여 주므로, 짧게 끝나는 작업은 -a 없이 보면 놓칠 수 있다. Compose ps의 표시 범위 (새 탭에서 열림), logs 옵션 (새 탭에서 열림)

뒤의 합성 예제에서 프로필을 켜지 않고 job-a만 지정한 뒤 조회하자 다음 두 출력이 나왔다.

job-a exited 0

job-a-1  | JOB_A_DONE

첫 줄은 ps 출력이고 마지막 줄은 로그다. 작업은 시작한 뒤 정상 종료했다. job-b와 base 컨테이너는 이 새 프로젝트에 생성되지 않았다. 기존 프로젝트에서는 예전 실행의 컨테이너가 남아 있을 수 있으므로, 목록에 있다는 사실만으로 이번 명령이 모두 시작했다고 판단하지 않는다. 출력이 비어 있다면 파일·프로젝트 이름과 이미 컨테이너를 정리했는지도 확인한다.

프로필 활성화와 서비스 지정을 비교했다

서비스 선택만 확인하려고 아래 세 작업을 별도로 실행했다. base에는 프로필이 없고, job-a와 job-b는 같은 tools 프로필을 사용한다. 모두 문자열 한 줄을 출력하고 끝나며, 서로 의존하지 않는다.

services:
  base:
    image: alpine:3.22
    command: ["sh", "-c", "printf 'BASE_DONE\n'"]
  job-a:
    image: alpine:3.22
    profiles: [tools]
    command: ["sh", "-c", "printf 'JOB_A_DONE\n'"]
  job-b:
    image: alpine:3.22
    profiles: [tools]
    command: ["sh", "-c", "printf 'JOB_B_DONE\n'"]

직접 비교하려면 Docker의 Linux 컨테이너와 Compose 플러그인을 사용할 수 있어야 한다. 빈 실습 폴더에 위 내용을 compose.yaml로 저장한다. 아래 명령은 로컬에 alpine:3.22 이미지가 있다는 조건이며, 없으면 먼저 docker pull alpine:3.22로 준비한다. --pull never는 비교 중 이미지를 새로 받지 않게 한다. 이미지가 없다는 오류가 나오면 서비스 선택 결과를 얻은 것이 아니다. up의 이미지 가져오기 옵션 (새 탭에서 열림)

다음 세 이름은 이 예제에서만 사용할 새 프로젝트 이름이다. 같은 이름의 프로젝트가 이미 있다면 사용하지 않는 이름으로 바꾼다. 셸과 .env에 COMPOSE_PROFILES가 지정되지 않은 상태에서, 각 줄을 실행하고 종료 코드가 0인지 확인한다. 세 명령은 각각 기본 실행, 프로필 활성화, 단일 서비스 지정을 비교한다.

docker compose -f .\compose.yaml -p pf-basic-40fb41 up -d --pull never
docker compose -f .\compose.yaml -p pf-tools-40fb41 --profile tools up -d --pull never
docker compose -f .\compose.yaml -p pf-target-40fb41 up -d --pull never job-a

각 프로젝트를 앞의 조회 명령에 같은 -f와 -p로 지정해 비교한다. 작업이 끝난 뒤 관찰한 서비스와 로그는 다음과 같았다. 프로젝트마다 새로 시작했으므로 앞선 실행의 컨테이너가 섞이지 않았다.

  • 일반 up: base만 생성됐고 로그는 BASE_DONE이었다.
  • --profile tools up: base, job-a, job-b가 생성됐고 세 작업의 DONE 로그가 모두 있었다.
  • up job-a: job-a만 생성됐고 로그는 JOB_A_DONE이었다.

생성된 컨테이너는 모두 exited, 종료 코드는 0이었다. 프로필 없는 base는 기본 실행에 포함되지만, 이름을 지정한 job-a의 의존성은 아니어서 세 번째 실행에는 포함되지 않았다. 기본 실행 대상이라는 뜻이 모든 명령에서 반드시 실행된다는 뜻은 아니다.

추가로 새 프로젝트에서 --profile tools up -d --pull never job-a도 실행했다. 이때도 job-a만 생성됐다. 이번 Compose에서는 프로필을 명시적으로 켜도 뒤에 지정한 실행 대상이 전체 프로필의 서비스로 넓어지지 않았다. 프로필 전체와 기본 서비스를 올리려는 경우에는 앞의 두 번째 명령처럼 서비스 이름을 붙이지 않는다.

일반 up에서도 프로필 작업이 생성된다면 명령의 --profile뿐 아니라 셸과 .env의 COMPOSE_PROFILES도 확인한다. 이 변수도 활성 프로필을 정한다. 이번 비교에서는 그 입력을 제외했다. Compose의 COMPOSE_PROFILES 설명 (새 탭에서 열림)

함께 필요한 서비스는 depends_on에서 찾는다

같은 파일의 job-a 아래에 depends_on: [base]를 추가하고 새 프로젝트에서 up -d --pull never job-a를 실행했다. 이번에는 base와 job-a가 생성됐고 두 작업의 로그가 남았다. job-b는 여전히 생성되지 않았다.

의존 대상을 depends_on: [job-b]로 바꾼 별도 실행에서는 job-a와 job-b가 생성됐고 base는 생성되지 않았다. 같은 프로필의 다른 작업이 함께 실행된 이유는 프로필을 공유해서가 아니라 지정한 작업의 의존 서비스였기 때문이다. 공식 프로필 명세도 같은 프로필의 의존 서비스를 직접 지정한 작업과 함께 실행하는 경우를 설명한다. 프로필과 의존성의 명세 예제 (새 탭에서 열림)

따라서 실행할 명령을 고를 때는 다음 세 가지를 확인한다.

  1. 평소 기본 서비스만 올리려면 프로필 활성화 없이 서비스 이름을 생략한다.
  2. 특정 작업과 그 의존 서비스만 필요하면 그 작업 이름을 지정하고 depends_on을 확인한다. 같은 프로필의 동료 작업은 의존성이나 명시 대상이 아니면 함께 실행될 것으로 기대하지 않는다.
  3. 프로필 전체와 기본 서비스를 함께 올리려면 --profile tools up처럼 프로필을 켜고 서비스 이름을 생략한다.

실습이 끝나면 만든 프로젝트만 정리한다. 예를 들어 docker compose -f .\compose.yaml -p pf-basic-40fb41 --profile "*" down으로 첫 프로젝트를 정리하고, 나머지 두 이름에도 각각 같은 명령을 적용한다. down의 기본 제거 대상은 서비스 컨테이너와 네트워크다. Compose down 설명 (새 탭에서 열림)

이 관찰은 Windows 11, Docker Desktop 4.92.0의 Linux 엔진 29.8.0, Compose v5.5.1에서 얻었다. 포트와 볼륨 없이 짧게 종료하는 합성 작업만 사용했고 생성한 컨테이너와 네트워크는 정리했다. 의존성 비교에는 --no-deps를 사용하지 않았다. 서로 다른 프로필에 걸린 의존성, 기존 컨테이너를 재사용하는 경우, 다른 Compose 버전은 실행하지 않았다. 함께 생성됐다는 관찰로 서비스 준비 완료나 실행 중 복구까지 보장하지는 않는다.

← 전체 글 보기