SSD Nodes Learn 8GB RAM — 연 $66
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-01

실서버 Docker Compose 명령어 치트시트

Compose V2에서 매일 쓰는 약 12개 명령을 작업별로 정리했습니다. 수명 주기, 변경 적용, 로그, 셸, 네트워크, volume과 안전한 정리 방법을 확인합니다.

실제로 사용하는 Compose 명령

Docker Compose는 40개가 넘는 하위 명령을 제공합니다. 서버에서 일상적으로 사용하는 명령은 약 12개입니다. 이 페이지에서는 수행하려는 작업에 따라 해당 명령을 분류하고, 각 명령의 용도를 한 가지 이유로 간단히 설명하며, 명령에 주의할 점이 있을 때는 자세한 설명으로 연결합니다.

이 문서의 모든 예시는 Compose V2를 사용합니다. 즉, 기존의 docker-compose 스크립트가 아니라 공백을 포함한 docker compose를 사용합니다. V2는 Docker Engine과 함께 설치되는 Go 플러그인입니다. 현재 패키지에서는 V1이 더 이상 제공되지 않으므로, 2026년 7월 기준으로 새 Ubuntu 시스템에서 docker-compose: command not found이 표시되는 것은 오류가 아니라 예상되는 동작입니다. docker compose version로 확인합니다. 아무것도 출력되지 않으면 docker-compose-plugin 패키지를 설치합니다.

아래의 모든 명령은 compose.yaml가 있는 디렉터리에서 실행합니다. Compose는 해당 디렉터리에서 프로젝트 이름을 가져오고 파일도 해당 디렉터리를 기준으로 찾기 때문입니다. 한 단계 상위 디렉터리에서 같은 명령을 실행하면 Compose가 no configuration file provided: not found와 함께 중지됩니다. 파일 형식 자체가 처음이라면 VPS에서 첫 Compose 파일 작성부터 시작한 다음 이 페이지로 돌아와 명령을 확인합니다.

수명 주기: 입력하는 4가지 명령과 컨테이너를 제거하는 1가지 명령

docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose down

up -d은 네트워크와 컨테이너를 생성하고 컨테이너를 시작한 후 반환합니다. 컨테이너가 생성된 즉시 반환하므로, 그 뒤에 curl 프로브를 실행하는 배포 스크립트는 첫 번째 시도에서 자주 실패합니다. up -d --wait은 healthcheck를 선언한 모든 서비스가 healthy를 보고할 때까지 대기하며, 서비스가 끝내 healthy 상태가 되지 않으면 0이 아닌 종료 코드를 반환합니다. 이 플래그의 효과는 검사 내용에 따라 달라집니다. 따라서 자동화에 사용하기 전에 Compose가 신뢰할 수 있는 healthcheck 작성 방법을 확인해야 합니다.

stop는 컨테이너를 중지하지만 유지하므로, start는 동일한 쓰기 가능 계층을 사용하는 동일한 컨테이너를 다시 시작합니다. down는 컨테이너를 중지한 다음 컨테이너와 프로젝트 네트워크를 제거합니다. volume 외부의 컨테이너 내부에 기록된 모든 데이터도 함께 삭제됩니다. 이는 Compose에서 가장 큰 오해를 일으키는 부분이며, down과 stop의 전체 차이에서 이 차이가 실제로 문제가 되는 지점을 설명합니다.

restart는 reload가 아닙니다. 이미 적용된 설정을 사용하는 동일한 컨테이너를 중지했다가 시작하므로, 변경된 환경 변수, 새 image tag 또는 수정된 port mapping은 전혀 적용되지 않습니다. 파일 변경 사항을 적용하려면 up -d를 다시 실행해야 합니다. Compose는 각 서비스를 실행 중인 컨테이너와 비교하고, 설정이 변경된 컨테이너만 다시 생성합니다.

변경 적용: 재생성, pull 또는 재빌드

docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build web

변경된 내용이 없으면 up -d 자체로는 아무 작업도 하지 않습니다. 따라서 반복해서 실행해도 안전합니다. --force-recreate는 이 비교를 무시하고 구성이 동일한 경우에도 모든 컨테이너를 교체합니다. 따라서 컨테이너 내부의 비정상 상태를 초기화하는 가장 빠른 방법입니다.

이미지를 업데이트하려면 두 명령이 필요합니다. 두 명령은 서로 다른 작업을 수행합니다. pull는 파일에 지정된 각 태그의 최신 이미지를 다운로드합니다. 그런 다음 up -d가 서비스의 이미지 ID가 실행 중인 컨테이너의 이미지 ID와 더 이상 일치하지 않는 것을 확인하고 컨테이너를 재생성합니다. pull을 건너뛰면 up -d가 지난달의 latest를 오류 없이 계속 실행합니다.

buildimage: 대신 build: 섹션을 선언하는 서비스에 적용됩니다. up -d --build는 한 단계로 빌드하고 시작합니다. 코드를 변경하는 동안 일반적으로 사용하는 작업 흐름입니다. 캐시된 레이어가 명백하게 오래된 경우에만 --no-cache를 사용합니다. 이 명령은 모든 레이어를 처음부터 다시 빌드하기 때문입니다.

실행 중인 항목 확인

docker compose ps
docker compose ps -a
docker compose logs -f --tail=100
docker compose logs --since 15m --timestamps db
docker compose top
docker compose ls

ps는 실행 중인 컨테이너만 나열합니다. 시작 중에 비정상 종료된 서비스는 -a를 추가하기 전까지 여기에 표시되지 않습니다. 따라서 ps에는 없지만 ps -a에는 Exited (1)로 표시되는 컨테이너는 일반적인 시작 실패 상태입니다. 종료 코드를 확인한 다음 로그를 확인합니다.

logs -f는 모든 서비스를 동시에 추적하고 각 줄 앞에 서비스 이름을 붙입니다. 서비스 간 통신이 발생하고 이벤트 순서가 중요한 경우에 필요한 화면입니다. 서비스 이름을 지정하면 범위를 좁힐 수 있습니다. 한 달 동안 실행된 컨테이너에서는 --tail=100가 중요합니다. 기본 동작은 전체 기록을 출력하므로 터미널에 너무 많은 내용이 표시되기 때문입니다. --since 15m는 일반적으로 필요한 질문에 답합니다. 방금 수행한 재시작 중에 무슨 일이 발생했는지 확인할 수 있습니다.

top는 각 컨테이너 내부의 프로세스를 나열합니다. 이를 통해 "컨테이너가 실행 중이다"와 "컨테이너 내부의 프로세스가 실행 중이다"를 구분할 수 있습니다. ls는 현재 디렉터리에서 벗어나 호스트의 모든 Compose 프로젝트와 상태를 나열합니다. 따라서 3개월 전에 시작한 스택을 찾을 수 있습니다.

서비스 내부에서 셸 열기

docker compose exec web sh
docker compose exec -u root web sh
docker compose run --rm web env
docker compose run --rm --no-deps web sh

exec는 이미 실행 중인 컨테이너 내부에서 명령을 실행합니다. run는 동일한 서비스 정의로 새 컨테이너를 시작합니다. 서비스가 너무 빨리 종료되어 exec로 접속할 수 없을 때 사용합니다. run은 항상 --rm과 함께 사용합니다. 이 옵션이 없으면 실행할 때마다 중지된 컨테이너가 남습니다. 이러한 컨테이너가 쌓이면 결국 docker compose ps -a을 읽을 수 없게 됩니다.

bash보다 먼저 sh을 시도합니다. Alpine 기반 이미지는 bash을 포함하지 않으므로 오류는 exec: "bash": executable file not found in $PATH으로 표시됩니다. run--no-deps를 추가하면 서비스의 종속 항목을 건너뜁니다. 따라서 간단한 설정 확인 때문에 전체 데이터베이스가 시작되는 일을 막을 수 있습니다.

run --rm web env은 각 .env 파일, environment: 블록 및 셸 변수를 모두 병합한 후 서비스가 실제로 받은 환경을 확인하는 가장 빠른 방법입니다. 값이 잘못되었다면 병합 순서가 원인인 경우가 많습니다. Compose가 env 파일과 시크릿을 확인하는 방식에서는 어떤 소스의 값이 우선하는지 설명합니다.

네트워크, 포트 및 이름 확인

docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networks

Compose는 모든 서비스를 하나의 프로젝트 네트워크에 연결하며, 각 서비스 이름은 해당 네트워크의 DNS 이름입니다. web 내부에서 getent hosts db를 실행하면 이름 확인이 정상적으로 작동할 때 컨테이너 IP가 출력되고, 작동하지 않을 때는 아무것도 출력되지 않습니다. 따라서 2초 안에 "이 컨테이너들이 서로 통신할 수 있는가"를 확인할 수 있습니다. 이름은 확인되지만 연결이 거부되면 db 내부의 프로세스가 0.0.0.0이 아니라 127.0.0.1에 바인딩된 것입니다. 따라서 다른 컨테이너에서 들어오는 패킷을 수락하지 않습니다. 이 모델의 나머지 내용은 Compose 네트워크와 서비스 DNS의 작동 방식에서 설명합니다.

port web 80는 컨테이너 포트가 게시된 호스트 주소와 포트를 출력합니다. 매핑이 변수에서 설정된 경우에도 추측할 필요가 없습니다. 포트를 게시하면 Docker가 직접 관리하는 방화벽 규칙도 작성합니다. 이 규칙은 사용자가 작성한 규칙보다 우선하므로, 비공개라고 생각한 서비스가 인터넷에 공개될 수 있습니다. 이 경우는 게시된 Docker 포트가 ufw 규칙을 우회하는 이유에서 설명합니다.

볼륨 및 데이터

docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -v

config --volumes는 프로젝트에서 선언한 이름 있는 볼륨을 한 줄에 하나씩 출력합니다. 이 목록을 백업해야 합니다. cp는 셸을 열지 않고 컨테이너 안팎으로 파일을 복사합니다. 컨테이너가 있는 쪽에는 service:path 형식을 사용합니다.

down -v는 컨테이너와 함께 해당 이름 있는 볼륨을 삭제합니다. 테스트 스택을 제거할 때는 적절한 명령이지만, 중요한 데이터가 있는 대상에는 사용하면 안 됩니다. 확인 절차가 없고 실행을 취소할 수 없기 때문입니다. 바인드 마운트는 호스트 파일 시스템에 있으므로 이 명령을 실행해도 유지됩니다. 이러한 영향 범위의 차이 때문에 바인드 마운트와 이름 있는 볼륨 중 하나를 신중하게 선택해야 합니다.

데이터 손실 없이 디스크 공간을 확보하는 정리

docker compose down --remove-orphans
docker system df
docker image prune -a
docker builder prune

--remove-orphans은(는) 프로젝트에 속하지만 파일에 더 이상 나타나지 않는 컨테이너를 삭제합니다. 서비스를 이름 변경한 후에는 정확히 이러한 컨테이너가 생성됩니다. 이 옵션이 없으면 해당 컨테이너는 계속 실행되지만 docker compose ps에는 표시되지 않습니다.

삭제하기 전에 docker system df을(를) 사용하면 디스크 공간 사용 현황을 확인할 수 있습니다. 이미지, 컨테이너, 로컬 볼륨 및 빌드 캐시를 각각 회수 가능한 공간과 함께 구분해 표시합니다. image prune -a은(는) 어떤 태그도 가리키지 않는 모든 이미지를 제거합니다. 대용량 이미지를 여러 버전 내려받은 서버에서는 일반적으로 가장 큰 효과를 얻을 수 있습니다. builder prune은(는) 빌드 캐시를 삭제합니다. 자체 이미지를 빌드하는 서버에서는 빌드 캐시가 계속 증가합니다.

이 옵션들은 named volume에는 영향을 주지 않습니다. named volume을 삭제하는 것은 docker volume prunedocker compose down -v뿐입니다.

문제가 발생하기 전에 파일 확인

docker compose config --quiet
docker compose config --services
docker compose --dry-run up -d

config --quiet은 성공 시 유효성만 검사하고 아무것도 출력하지 않습니다. 따라서 사전 배포 단계나 git hook에 사용해야 합니다. 일반적인 config은 병합 및 보간이 모두 적용된 파일을 출력합니다. 이를 통해 변수가 확인되었는지, override 파일이 예상한 방식으로 계층화되었는지 확인할 수 있습니다. 설정되지 않은 변수는 경고 The "X" variable is not set. Defaulting to a blank string. 옆에 빈 값으로 표시됩니다.

--dry-run은 subcommand flag가 아니라 전역 flag입니다. 따라서 up 앞에 사용해야 합니다. 이 옵션은 Compose가 수행할 모든 작업을 출력하지만 실제로 변경하지는 않습니다. 중요한 stack에서 down을 실행하기 전에 30초를 투자할 가치가 있습니다.

파일, 프로필 및 프로젝트 간 작업

docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose --profile debug up -d
docker compose -p staging up -d

여러 -f 플래그는 순서대로 병합되며, 나중에 지정된 파일이 키 단위로 이전 파일을 덮어씁니다. 하나의 기본 파일과 작은 production 재정의 파일을 유지할 때 사용하는 표준 방법입니다. 단, 목록과 맵에는 규칙이 다르게 적용됩니다. 예상하지 못한 결과를 디버깅하기 전에 Compose가 여러 파일을 병합하는 방식을 읽으십시오.

--profile은 해당 프로필로 태그된 서비스를 태그되지 않은 서비스와 함께 시작합니다. 따라서 일반 up에서 debug 도구를 제외할 수 있습니다. -p는 프로젝트 이름을 설정하므로, 하나의 stack 사본 2개를 별도의 네트워크와 별도의 volume 이름으로 나란히 실행할 수 있습니다. 재부팅 후 stack을 복구하는 작업에는 직접 입력하는 명령이 필요하지 않습니다. 대신 이를 대신 실행하는 unit을 사용하며, 자세한 내용은 부팅 시 Compose stack 시작에 설명되어 있습니다.

FAQ

하이픈이 포함된 docker-compose를 대체한 것은 무엇입니까?

공백을 사용하여 docker compose로 호출하는 Compose V2입니다. Docker Engine에 번들로 포함된 플러그인이며, 현재 패키지에는 V1 Python 도구가 더 이상 설치되지 않습니다. 공백 형식으로 실행해도 아무것도 출력되지 않으면 배포판에 맞는 docker-compose-plugin 패키지를 설치합니다. V2에는 V1에 없던 플래그가 있으므로 별칭을 추가하지 말고 기존 스크립트를 공백 형식으로 업데이트합니다.

docker compose restart가 구성 변경을 반영하지 않는 이유는 무엇입니까?

restart는 기존 컨테이너를 생성 당시의 구성으로 중지했다가 다시 시작하며, compose.yaml를 다시 읽지 않습니다. 환경 변수, 포트, 볼륨 또는 이미지 태그를 변경한 경우에는 docker compose up -d가 필요합니다. docker compose up -d는 각 서비스를 실행 중인 컨테이너와 비교하고, 차이가 있는 컨테이너를 다시 생성합니다. 파일의 내용이 변경되지 않았더라도 교체하려면 --force-recreate를 추가합니다.

서비스를 최신 이미지로 업데이트하려면 어떻게 해야 합니까?

docker compose pull를 실행한 다음 docker compose up -d를 실행합니다. pull 작업은 파일에 지정된 각 태그의 최신 이미지를 가져오며, up -d는 이미지 ID가 컨테이너와 더 이상 일치하지 않는 서비스를 다시 생성합니다. up -d만 실행하면 디스크에 이미 있는 이미지를 재사용합니다. 따라서 latest에 고정된 스택이 오류를 출력하지 않은 채 수개월 전 빌드로 실행될 수 있습니다.

실행 중인 서버에서 어떤 정리 명령을 안전하게 사용할 수 있습니까?

docker system df, docker image prune -adocker builder prune은 이미지만 제거하고 캐시는 정리하므로 실행 중인 서비스는 계속 작동하며 named volume은 변경되지 않습니다. 위험한 조합은 docker compose down -vdocker volume prune입니다. 이 명령은 확인 없이 named volume을 삭제합니다. 먼저 docker compose config --volumes를 실행하여 영향을 받을 항목을 확인합니다.

전체 스택을 시작하지 않고 하나의 명령만 실행할 수 있습니까?

예. docker compose run --rm --no-deps web shweb 서비스 정의에서 단일 컨테이너를 시작하고, 종속성을 건너뛰며, 종료할 때 컨테이너를 제거합니다. 컨테이너가 이미 실행 중이면 exec를 사용합니다. exec는 실행 중인 프로세스에 연결하여 서비스의 실제 상태를 보여줍니다.