본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 26. · 2 Views
Docker CLI 기본 명령어 완벽 가이드
Docker를 처음 접하는 초급 개발자를 위한 필수 CLI 명령어 가이드입니다. 컨테이너의 생성부터 삭제까지, 실무에서 매일 사용하는 핵심 명령어를 쉽게 설명합니다.
목차
- docker_run_명령어_상세
- docker_ps로_컨테이너_조회
- docker_logs_로그_확인
- docker_exec로_컨테이너_접속
- docker_stop_start_restart
- docker_rm과_docker_rmi
1. docker run 명령어 상세
김개발 씨는 오늘 처음으로 Docker를 사용해보기로 했습니다. 팀에서 "이제 개발 환경은 Docker로 통일합니다"라는 공지가 내려왔기 때문입니다.
터미널 앞에 앉아 막막하게 화면을 바라보던 그때, 선배 박시니어 씨가 다가왔습니다. "Docker의 시작은 바로 run 명령어야.
이것만 알면 반은 성공한 거야."
docker run은 Docker의 가장 기본이자 핵심 명령어입니다. 이 명령어는 이미지를 기반으로 새로운 컨테이너를 생성하고 실행합니다.
마치 설계도를 보고 실제 건물을 짓는 것과 같습니다. 이 명령어 하나에 컨테이너의 이름, 포트, 환경변수 등 모든 설정을 담을 수 있습니다.
다음 코드를 살펴봅시다.
# 기본 실행: nginx 웹 서버 컨테이너 시작
docker run nginx
# 백그라운드 실행 (-d: detached mode)
docker run -d nginx
# 컨테이너 이름 지정
docker run -d --name my-web-server nginx
# 포트 매핑: 호스트 8080 -> 컨테이너 80
docker run -d -p 8080:80 --name my-nginx nginx
# 환경변수 설정과 볼륨 마운트 함께 사용
docker run -d \
--name my-app \
-p 3000:3000 \
-e NODE_ENV=production \
-v $(pwd)/data:/app/data \
node:18-alpine
김개발 씨는 입사 6개월 차 주니어 개발자입니다. 지금까지는 로컬에 직접 Node.js와 MySQL을 설치해서 개발해왔습니다.
그런데 새 프로젝트에서는 모든 팀원이 Docker를 사용한다고 합니다. "설치할 것도 없고 그냥 명령어 하나면 된다"는 선배의 말에 반신반의하며 터미널을 열었습니다.
박시니어 씨가 김개발 씨 옆에 앉아 차근차근 설명을 시작합니다. "Docker에서 가장 먼저 알아야 할 건 docker run 명령어야.
이게 뭐냐면, 마치 붕어빵 틀로 붕어빵을 찍어내는 것과 같아." 그렇다면 docker run이란 정확히 무엇일까요? 쉽게 비유하자면, 이미지는 붕어빵 틀이고 컨테이너는 그 틀에서 찍어낸 실제 붕어빵입니다.
docker run 명령어는 바로 이 "찍어내는" 과정을 담당합니다. 같은 틀에서 붕어빵을 여러 개 만들 수 있듯이, 하나의 이미지로 여러 개의 컨테이너를 생성할 수 있습니다.
Docker가 없던 시절에는 어땠을까요? 개발자들은 새 프로젝트를 시작할 때마다 필요한 소프트웨어를 직접 설치해야 했습니다.
Node.js 버전이 맞지 않아 에러가 나고, MySQL 설정이 달라서 데이터베이스 연결이 안 되는 일이 비일비재했습니다. "내 컴퓨터에서는 되는데요?"라는 말이 개발자들 사이에서 유행어처럼 번진 이유입니다.
바로 이런 문제를 해결하기 위해 Docker가 등장했습니다. docker run 명령어를 사용하면 누구나 동일한 환경을 즉시 구축할 수 있습니다.
설치 과정에서 생기는 오류도 없고, 버전 충돌도 없습니다. 무엇보다 한 줄의 명령어로 복잡한 환경이 순식간에 만들어집니다.
위의 코드를 하나씩 살펴보겠습니다. 가장 기본적인 형태는 docker run nginx입니다.
이렇게 하면 nginx 이미지를 다운로드받고(없다면) 컨테이너를 생성하여 실행합니다. 하지만 이 상태에서는 터미널이 컨테이너에 붙잡혀 다른 작업을 할 수 없습니다.
그래서 -d 옵션을 사용합니다. d는 detached의 약자로, 컨테이너를 백그라운드에서 실행합니다.
마치 음악을 틀어놓고 다른 일을 하는 것처럼, 컨테이너는 뒤에서 돌아가고 우리는 터미널을 계속 사용할 수 있습니다. --name 옵션은 컨테이너에 이름을 붙여줍니다.
이름을 지정하지 않으면 Docker가 임의로 이상한 이름을 만들어냅니다. "quirky_einstein" 같은 이름보다는 "my-web-server"가 훨씬 관리하기 편하겠죠?
-p 옵션은 포트 매핑을 담당합니다. 컨테이너는 격리된 공간이라 외부에서 접근하려면 문을 열어줘야 합니다.
-p 8080:80은 "호스트의 8080번 포트로 들어오면 컨테이너의 80번 포트로 연결해줘"라는 의미입니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 웹 서비스를 개발한다고 가정해봅시다. 프론트엔드 개발자는 nginx 컨테이너를, 백엔드 개발자는 node 컨테이너를, DBA는 mysql 컨테이너를 각자 실행합니다.
모두 같은 버전, 같은 설정으로요. "내 컴퓨터에서는 되는데"라는 말은 이제 역사 속으로 사라집니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 -d 옵션 없이 실행하는 것입니다.
그러면 터미널이 컨테이너에 붙잡혀서 Ctrl+C를 누르면 컨테이너가 종료됩니다. 또한 포트 충돌도 조심해야 합니다.
이미 8080 포트를 사용 중인데 같은 포트로 컨테이너를 실행하면 에러가 발생합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 설명을 들은 김개발 씨가 직접 명령어를 입력해봤습니다. 정말 한 줄의 명령어로 nginx 서버가 실행되었습니다.
브라우저에서 localhost:8080을 열자 "Welcome to nginx!" 페이지가 나타났습니다. "이게 진짜 되네요!" docker run 명령어를 제대로 이해하면 어떤 개발 환경이든 순식간에 구축할 수 있습니다.
여러분도 오늘 배운 옵션들을 조합해서 자신만의 개발 환경을 만들어 보세요.
실전 팁
💡 - 컨테이너 이름은 프로젝트명-역할 형태로 짓는 것이 관리하기 편합니다 (예: myapp-db, myapp-web)
- -p 옵션에서 앞의 숫자가 호스트, 뒤의 숫자가 컨테이너 포트입니다. 순서를 헷갈리지 마세요
- --rm 옵션을 추가하면 컨테이너 종료 시 자동으로 삭제되어 테스트용으로 유용합니다
2. docker ps로 컨테이너 조회
김개발 씨가 여러 개의 컨테이너를 실행하다 보니 문득 궁금해졌습니다. "지금 내 컴퓨터에서 몇 개의 컨테이너가 돌아가고 있는 거지?" 창문 밖을 보며 생각에 잠겨있을 때 박시니어 씨가 말했습니다.
"그럴 땐 docker ps를 써봐. 지금 뭐가 돌아가는지 다 보여줄 거야."
docker ps는 현재 실행 중인 컨테이너 목록을 보여주는 명령어입니다. 마치 작업 관리자에서 실행 중인 프로그램을 확인하는 것과 같습니다.
컨테이너 ID, 이름, 상태, 포트 정보 등을 한눈에 파악할 수 있습니다. -a 옵션을 추가하면 중지된 컨테이너까지 모두 확인할 수 있습니다.
다음 코드를 살펴봅시다.
# 실행 중인 컨테이너만 조회
docker ps
# 모든 컨테이너 조회 (중지된 것 포함)
docker ps -a
# 컨테이너 ID만 출력 (스크립트에서 유용)
docker ps -q
# 모든 컨테이너의 ID만 출력
docker ps -aq
# 특정 조건으로 필터링 (이름에 web 포함)
docker ps -f "name=web"
# 출력 형식 커스터마이징
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
김개발 씨의 맥북에는 어느새 컨테이너가 5개나 실행되고 있었습니다. nginx도 있고, mysql도 있고, 테스트용으로 띄웠던 redis도 있습니다.
문제는 어떤 게 어떤 건지 헷갈리기 시작했다는 점입니다. "분명 아까 웹 서버를 띄웠는데, 지금 돌아가고 있는 건가?" 박시니어 씨가 웃으며 말합니다.
"컨테이너를 관리하려면 먼저 뭐가 있는지 알아야지. docker ps 명령어를 쳐봐." 그렇다면 docker ps란 정확히 무엇일까요?
쉽게 비유하자면, docker ps는 마치 회사의 출퇴근 기록부와 같습니다. 누가 지금 사무실에 있는지, 언제 출근했는지, 어느 자리에 앉아있는지 한눈에 볼 수 있습니다.
Docker에서도 마찬가지로 어떤 컨테이너가 실행 중인지, 언제 시작되었는지, 어떤 포트를 사용하는지 확인할 수 있습니다. 컨테이너 상태를 모르면 어떤 문제가 생길까요?
포트 충돌이 대표적입니다. 이미 8080 포트를 사용하는 컨테이너가 있는데 같은 포트로 새 컨테이너를 띄우면 에러가 발생합니다.
또한 리소스 낭비도 심각합니다. 쓰지도 않는 컨테이너가 메모리를 차지하고 있을 수 있습니다.
docker ps 명령어를 실행하면 여러 가지 정보가 표시됩니다. CONTAINER ID는 컨테이너의 고유 식별자입니다.
전체 ID는 64자이지만 앞의 12자만 보여줍니다. 대부분의 경우 이 짧은 ID만으로도 충분히 컨테이너를 특정할 수 있습니다.
IMAGE는 컨테이너가 어떤 이미지로 만들어졌는지 알려줍니다. nginx인지, mysql인지, node인지 바로 확인할 수 있습니다.
COMMAND는 컨테이너가 실행할 때 수행한 명령어입니다. 웹 서버라면 nginx를 시작하는 명령어가, 데이터베이스라면 mysqld를 시작하는 명령어가 표시됩니다.
CREATED는 컨테이너가 생성된 시간을 알려줍니다. "2 hours ago" 같은 형태로 표시되어 언제 만들었는지 쉽게 파악할 수 있습니다.
STATUS는 현재 상태를 보여줍니다. "Up 2 hours"라면 2시간째 실행 중이라는 뜻입니다.
"Exited (0) 5 minutes ago"라면 5분 전에 정상 종료되었다는 의미입니다. PORTS는 포트 매핑 정보입니다.
"0.0.0.0:8080->80/tcp"는 호스트의 8080 포트가 컨테이너의 80 포트와 연결되어 있다는 뜻입니다. NAMES는 컨테이너 이름입니다.
--name 옵션으로 지정한 이름이 여기에 표시됩니다. 실제 현업에서는 어떻게 활용할까요?
운영 서버에서는 수십 개의 컨테이너가 돌아갈 수 있습니다. 이때 --format 옵션을 활용하면 필요한 정보만 깔끔하게 볼 수 있습니다.
또한 -f 옵션으로 특정 이름이나 상태를 가진 컨테이너만 필터링할 수도 있습니다. 스크립트를 작성할 때는 -q 옵션이 매우 유용합니다.
컨테이너 ID만 출력하기 때문에 다른 명령어와 조합하기 좋습니다. 예를 들어 **docker stop $(docker ps -q)**라고 하면 실행 중인 모든 컨테이너를 한 번에 중지할 수 있습니다.
주의할 점도 있습니다. docker ps는 기본적으로 실행 중인 컨테이너만 보여줍니다.
중지된 컨테이너를 보려면 반드시 -a 옵션을 붙여야 합니다. 초보자들이 "컨테이너가 사라졌어요!"라고 당황할 때, 대부분 이 옵션을 빼먹은 경우입니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. docker ps를 실행하자 화면에 표가 나타났습니다.
현재 3개의 컨테이너가 실행 중이었고, docker ps -a를 실행하니 중지된 컨테이너 2개도 보였습니다. "아, 이래서 포트 충돌이 났구나.
이미 8080을 쓰고 있었네." docker ps 명령어를 잘 활용하면 컨테이너 관리가 훨씬 수월해집니다. 현재 상태를 정확히 파악하는 것이 모든 관리의 시작입니다.
실전 팁
💡 - docker ps -a를 습관적으로 사용하세요. 중지된 컨테이너가 디스크 공간을 차지하고 있을 수 있습니다
- --format 옵션으로 자주 쓰는 형식을 alias로 등록해두면 편리합니다
- docker ps -q와 다른 명령어를 조합하면 일괄 작업이 가능합니다
3. docker logs 로그 확인
김개발 씨가 띄운 웹 서버에 접속이 안 됩니다. 분명 컨테이너는 실행 중인데 브라우저에서 아무것도 안 뜹니다.
"대체 뭐가 문제지?" 머리를 긁적이던 김개발 씨에게 박시니어 씨가 한마디 합니다. "에러가 났을 때 제일 먼저 해야 할 일은 뭐게?
바로 로그를 보는 거야."
docker logs는 컨테이너의 로그를 확인하는 명령어입니다. 컨테이너 내부에서 출력되는 모든 메시지를 볼 수 있습니다.
마치 블랙박스 영상을 확인하는 것처럼, 컨테이너 안에서 무슨 일이 일어났는지 추적할 수 있습니다. 에러 메시지, 접속 기록, 경고 메시지 등 문제 해결에 필수적인 정보를 제공합니다.
다음 코드를 살펴봅시다.
# 컨테이너 로그 전체 확인
docker logs my-nginx
# 마지막 100줄만 확인
docker logs --tail 100 my-nginx
# 실시간 로그 스트리밍 (tail -f 처럼)
docker logs -f my-nginx
# 타임스탬프와 함께 출력
docker logs -t my-nginx
# 특정 시간 이후 로그만 확인
docker logs --since 2h my-nginx
# 특정 시간까지의 로그만 확인
docker logs --until 1h my-nginx
# 조합: 최근 2시간, 마지막 50줄, 실시간 스트리밍
docker logs --since 2h --tail 50 -f my-nginx
금요일 오후 5시, 김개발 씨는 퇴근을 앞두고 마지막 테스트를 진행 중이었습니다. 그런데 이상합니다.
방금까지 잘 되던 API가 갑자기 응답을 하지 않습니다. docker ps로 확인해보니 컨테이너는 분명 "Up" 상태입니다.
도대체 뭐가 문제일까요? 박시니어 씨가 김개발 씨의 화면을 보더니 말합니다.
"컨테이너가 살아있다고 정상인 건 아니야. 내부에서 에러가 났을 수도 있지.
docker logs로 확인해봐." 그렇다면 docker logs란 정확히 무엇일까요? 쉽게 비유하자면, 컨테이너는 일종의 밀폐된 방과 같습니다.
외부에서는 방 안에서 무슨 일이 벌어지는지 알 수 없습니다. docker logs는 그 방에 설치된 CCTV 녹화 영상입니다.
방 안에서 일어난 모든 일을 기록해두었다가 필요할 때 확인할 수 있습니다. 로그가 없다면 개발자는 어떻게 될까요?
에러가 발생해도 원인을 알 수 없습니다. "뭔가 안 되는데 뭐가 안 되는지 모르겠어요"라는 최악의 상황에 빠지게 됩니다.
특히 컨테이너 환경에서는 내부에 직접 접속하기가 번거롭기 때문에 로그의 중요성이 더욱 커집니다. docker logs 명령어는 여러 가지 유용한 옵션을 제공합니다.
-f 옵션은 follow의 약자로, 실시간으로 로그를 스트리밍합니다. 마치 터미널에서 tail -f를 사용하는 것과 같습니다.
새로운 로그가 찍힐 때마다 화면에 바로 나타납니다. 실시간 디버깅에 필수적인 옵션입니다.
--tail 옵션은 최근 몇 줄만 보여줍니다. 컨테이너가 오래 실행되었다면 로그가 수만 줄에 달할 수 있습니다.
--tail 100을 사용하면 마지막 100줄만 깔끔하게 볼 수 있습니다. -t 옵션은 타임스탬프를 함께 출력합니다.
언제 발생한 로그인지 시간 정보가 함께 나타나 문제 발생 시점을 특정하기 쉬워집니다. --since와 --until 옵션은 시간 범위를 지정합니다.
"최근 2시간 동안의 로그만 봐야지"라고 할 때 --since 2h를 사용합니다. 특정 시점의 문제를 조사할 때 매우 유용합니다.
실제 현업에서는 어떻게 활용할까요? 서버에 문제가 생겼다는 알림을 받았을 때, 가장 먼저 하는 일이 로그 확인입니다.
docker logs --since 30m --tail 200 -f my-app 같은 명령어로 최근 30분간의 로그 중 마지막 200줄을 보면서 실시간 상황도 모니터링합니다. 대부분의 문제는 로그만 잘 봐도 원인을 파악할 수 있습니다.
주의할 점도 있습니다. 로그가 너무 많으면 메모리와 디스크를 과도하게 사용할 수 있습니다.
프로덕션 환경에서는 로그 로테이션을 설정하거나 별도의 로그 관리 시스템을 사용해야 합니다. 또한 -f 옵션을 쓸 때는 Ctrl+C로 빠져나와야 한다는 것을 잊지 마세요.
다시 김개발 씨의 이야기로 돌아가 봅시다. docker logs my-app을 실행하자 화면에 빨간 글씨가 나타났습니다.
"Error: Cannot connect to database at localhost:3306". 아, 데이터베이스 컨테이너가 중지되어 있었던 것입니다!
로그 하나로 문제의 원인을 바로 찾았습니다. docker logs는 컨테이너 문제 해결의 첫 번째 도구입니다.
뭔가 이상하다 싶으면 일단 로그부터 확인하세요. 답은 거기에 있습니다.
실전 팁
💡 - 에러가 발생하면 무조건 docker logs부터 확인하는 습관을 들이세요
- -f와 --tail을 함께 쓰면 최근 로그를 보면서 실시간 모니터링이 가능합니다
- 로그가 JSON 형식이라면 jq와 파이프로 연결하여 예쁘게 출력할 수 있습니다
4. docker exec로 컨테이너 접속
로그만으로는 문제를 해결할 수 없을 때가 있습니다. 김개발 씨도 그런 상황에 부딪혔습니다.
설정 파일을 직접 확인하고 싶은데 컨테이너 안에 어떻게 들어가야 할지 모르겠습니다. "이건 마치 유리창 너머로만 방 안을 보는 느낌이에요." 박시니어 씨가 미소 짓습니다.
"그럼 이제 방 안으로 들어가는 법을 알려줄게."
docker exec는 실행 중인 컨테이너 내부에서 명령어를 실행하는 기능입니다. 마치 원격 접속으로 서버에 들어가는 것처럼, 컨테이너 안으로 직접 들어가서 파일을 확인하거나 명령어를 실행할 수 있습니다.
디버깅, 설정 확인, 수동 작업 등에 필수적인 명령어입니다.
다음 코드를 살펴봅시다.
# 컨테이너 내부에서 단일 명령어 실행
docker exec my-nginx cat /etc/nginx/nginx.conf
# 컨테이너에 대화형 쉘로 접속
docker exec -it my-nginx /bin/bash
# Alpine 기반 이미지는 sh 사용
docker exec -it my-alpine /bin/sh
# 특정 사용자로 명령어 실행
docker exec -u root my-app whoami
# 환경변수 설정하고 명령어 실행
docker exec -e DEBUG=true my-app npm run test
# 작업 디렉토리 지정
docker exec -w /app my-node ls -la
# 조합: root 사용자로 대화형 bash 접속
docker exec -it -u root my-ubuntu /bin/bash
김개발 씨는 nginx 설정을 확인해야 했습니다. nginx.conf 파일을 수정해서 이미지를 새로 빌드해야 하는지, 아니면 현재 설정으로도 충분한지 판단해야 합니다.
하지만 컨테이너 안의 파일을 어떻게 볼 수 있을까요? 박시니어 씨가 설명합니다.
"docker exec를 쓰면 컨테이너 안에서 명령어를 실행할 수 있어. 마치 SSH로 서버에 접속하는 것처럼 말이야." 그렇다면 docker exec란 정확히 무엇일까요?
쉽게 비유하자면, 컨테이너는 밀봉된 상자와 같습니다. 보통은 외부에서 상자 안을 들여다볼 수 없습니다.
하지만 docker exec는 그 상자에 잠시 문을 열고 손을 넣어 내부를 만져볼 수 있게 해줍니다. 물건을 꺼내볼 수도 있고, 안에 있는 스위치를 조작할 수도 있습니다.
컨테이너에 직접 접속하지 못하면 어떤 문제가 생길까요? 설정 파일을 확인하려면 이미지를 뜯어봐야 합니다.
로그 파일이 어떤 형식인지 알려면 문서를 뒤져야 합니다. 데이터베이스에 직접 쿼리를 날려보고 싶어도 방법이 없습니다.
모든 확인 작업이 간접적으로만 가능해져서 디버깅 시간이 크게 늘어납니다. docker exec 명령어의 핵심 옵션들을 살펴보겠습니다.
-i 옵션은 interactive의 약자로, 표준 입력을 열어둡니다. 키보드 입력을 컨테이너로 전달할 수 있게 됩니다.
-t 옵션은 tty의 약자로, 가상 터미널을 할당합니다. 이 옵션이 없으면 프롬프트가 제대로 표시되지 않습니다.
대부분의 경우 -it를 함께 사용합니다. 이렇게 하면 마치 진짜 서버에 SSH로 접속한 것처럼 컨테이너 내부를 자유롭게 탐색할 수 있습니다.
위의 코드 예제를 살펴보겠습니다. docker exec my-nginx cat /etc/nginx/nginx.conf는 컨테이너에 잠깐 들어가서 nginx.conf 파일 내용만 출력하고 바로 나옵니다.
단순히 파일 내용만 확인하고 싶을 때 유용합니다. docker exec -it my-nginx /bin/bash는 컨테이너 안에서 bash 쉘을 실행하고 대화형으로 접속합니다.
exit를 입력하면 컨테이너에서 빠져나올 수 있습니다. 단, 컨테이너가 종료되는 것은 아닙니다.
Alpine Linux 기반 이미지는 bash가 없는 경우가 많습니다. 이럴 때는 /bin/sh를 사용해야 합니다.
Alpine은 용량을 줄이기 위해 최소한의 도구만 포함하기 때문입니다. 실제 현업에서는 어떻게 활용할까요?
데이터베이스 컨테이너에서 직접 쿼리를 실행하고 싶을 때 docker exec -it my-mysql mysql -u root -p를 사용합니다. 웹 서버의 설정을 확인할 때, 애플리케이션의 환경변수를 체크할 때, 로그 파일을 직접 조회할 때 모두 docker exec가 활약합니다.
하지만 주의할 점도 있습니다. docker exec로 컨테이너 내부를 수정하면 컨테이너가 재시작될 때 변경사항이 사라집니다.
컨테이너는 이미지 기반으로 만들어지기 때문입니다. 영구적인 수정이 필요하다면 이미지를 새로 빌드하거나 볼륨 마운트를 활용해야 합니다.
또한 프로덕션 환경에서는 가급적 exec 사용을 자제해야 합니다. 수동 작업은 추적이 어렵고 실수가 발생하기 쉽습니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. docker exec -it my-nginx /bin/bash를 입력하자 프롬프트가 바뀌었습니다.
이제 컨테이너 안입니다! cat /etc/nginx/nginx.conf로 설정을 확인하고, ls -la로 파일 목록을 살펴보았습니다.
문제의 원인을 직접 눈으로 확인할 수 있었습니다. docker exec는 컨테이너 내부를 탐험하는 열쇠입니다.
디버깅이 막힐 때, 설정을 확인하고 싶을 때, 이 명령어를 떠올리세요.
실전 팁
💡 - -it는 거의 항상 함께 사용합니다. 외우세요: "docker exec -it"
- Alpine 기반 이미지에서는 bash 대신 sh를 사용해야 합니다
- exec로 수정한 내용은 컨테이너 재시작 시 사라진다는 점을 명심하세요
5. docker stop start restart
김개발 씨가 설정을 변경했습니다. 이제 컨테이너를 재시작해야 새로운 설정이 적용됩니다.
그런데 컨테이너를 어떻게 끄고 켜는 걸까요? "그냥 docker run을 다시 하면 되나요?" 박시니어 씨가 고개를 젓습니다.
"그러면 새 컨테이너가 만들어지지. 기존 컨테이너를 제어하는 방법을 알아야 해."
docker stop, docker start, docker restart는 컨테이너의 생명주기를 제어하는 명령어입니다. 마치 컴퓨터의 전원 버튼처럼, 컨테이너를 끄고, 켜고, 재시작할 수 있습니다.
stop은 실행 중인 컨테이너를 중지하고, start는 중지된 컨테이너를 다시 시작하며, restart는 이 두 과정을 한 번에 수행합니다.
다음 코드를 살펴봅시다.
# 컨테이너 중지 (SIGTERM 신호 전송, 10초 후 SIGKILL)
docker stop my-nginx
# 여러 컨테이너 동시에 중지
docker stop my-nginx my-mysql my-redis
# 중지 대기 시간 지정 (5초 후 강제 종료)
docker stop -t 5 my-nginx
# 중지된 컨테이너 시작
docker start my-nginx
# 컨테이너 재시작 (stop + start)
docker restart my-nginx
# 강제 종료 (SIGKILL, 즉시 종료)
docker kill my-nginx
# 실행 중인 모든 컨테이너 중지
docker stop $(docker ps -q)
김개발 씨의 애플리케이션에서 버그가 발견되었습니다. 코드를 수정하고 다시 배포해야 합니다.
그런데 "컨테이너를 어떻게 내려야 하지?"라는 의문이 생겼습니다. Ctrl+C를 누르면 되나요?
터미널을 닫으면 꺼지나요? 박시니어 씨가 차근차근 설명합니다.
"컨테이너를 제어하는 건 세 가지 명령어만 알면 돼. stop, start, restart.
컴퓨터 전원 버튼이라고 생각하면 쉬워." 그렇다면 이 세 가지 명령어는 어떻게 다를까요? docker stop은 컨테이너에게 "이제 종료할 거야, 하던 일 정리해"라고 정중하게 알려주는 것입니다.
마치 퇴근 전에 "10분 뒤에 불 끕니다"라고 방송하는 것과 같습니다. 컨테이너는 SIGTERM 신호를 받고 연결을 정리하고, 파일을 저장하고, 깔끔하게 종료합니다.
만약 10초가 지나도 종료되지 않으면? Docker는 SIGKILL 신호를 보내서 강제로 종료합니다.
이건 "지금 당장 나가!"와 같습니다. -t 옵션으로 이 대기 시간을 조절할 수 있습니다.
docker start는 중지된 컨테이너를 다시 깨우는 명령어입니다. 중요한 점은 새 컨테이너를 만드는 게 아니라 기존 컨테이너를 그대로 시작한다는 것입니다.
중지 전의 상태가 그대로 유지됩니다. docker restart는 stop과 start를 한 번에 수행합니다.
설정을 변경했거나 메모리를 정리하고 싶을 때 자주 사용합니다. docker kill은 어떨까요?
이건 경고 없이 바로 SIGKILL을 보냅니다. 컨테이너가 응답하지 않을 때 최후의 수단으로 사용합니다.
정상적인 상황에서는 stop을 쓰는 것이 좋습니다. 실제 현업에서는 어떻게 활용할까요?
배포 과정에서 docker stop으로 기존 컨테이너를 중지하고, 새 이미지로 docker run을 실행하는 것이 일반적입니다. 간단한 설정 변경이라면 docker restart만으로 충분할 때도 있습니다.
여러 컨테이너를 관리할 때는 **docker stop $(docker ps -q)**로 한 번에 중지하는 패턴을 자주 씁니다. 주의할 점도 있습니다.
stop과 rm을 혼동하지 마세요. stop은 컨테이너를 중지만 하고, rm은 삭제합니다.
중지된 컨테이너는 다시 start로 시작할 수 있지만, 삭제된 컨테이너는 복구할 수 없습니다. 또한 데이터를 볼륨에 저장하지 않았다면 컨테이너 삭제 시 데이터도 함께 사라진다는 점을 명심하세요.
다시 김개발 씨의 이야기로 돌아가 봅시다. docker stop my-app을 실행하자 컨테이너가 깔끔하게 종료되었습니다.
새 이미지를 빌드하고 docker run으로 새 컨테이너를 시작했습니다. 버그가 수정된 버전이 성공적으로 배포되었습니다.
stop, start, restart는 컨테이너 운영의 기본입니다. 이 세 가지만 알아도 컨테이너를 자유자재로 제어할 수 있습니다.
실전 팁
💡 - 가능하면 docker kill 대신 docker stop을 사용하세요. 데이터 손실을 방지할 수 있습니다
- docker restart는 설정 파일을 다시 읽어야 할 때 유용합니다
- docker stop $(docker ps -q)로 모든 컨테이너를 한 번에 중지할 수 있습니다
6. docker rm과 docker rmi
김개발 씨가 docker ps -a를 실행했더니 수십 개의 컨테이너가 나열되었습니다. 대부분 "Exited" 상태인 테스트용 컨테이너들입니다.
디스크 사용량 경고까지 뜨기 시작했습니다. "이 쓸모없는 컨테이너들을 어떻게 정리하죠?" 박시니어 씨가 대답합니다.
"그래, 이제 청소하는 법을 배울 때가 됐군."
docker rm은 컨테이너를 삭제하는 명령어이고, docker rmi는 이미지를 삭제하는 명령어입니다. rm은 remove의 약자이고, rmi는 remove image의 약자입니다.
마치 휴지통을 비우는 것처럼, 더 이상 필요 없는 컨테이너와 이미지를 정리하여 디스크 공간을 확보합니다.
다음 코드를 살펴봅시다.
# 중지된 컨테이너 삭제
docker rm my-old-container
# 여러 컨테이너 동시 삭제
docker rm container1 container2 container3
# 실행 중인 컨테이너 강제 삭제
docker rm -f my-running-container
# 중지된 모든 컨테이너 삭제
docker rm $(docker ps -aq -f status=exited)
# 이미지 삭제
docker rmi nginx:latest
# 여러 이미지 동시 삭제
docker rmi nginx:1.19 nginx:1.20 nginx:1.21
# 이름 없는 이미지 (dangling) 삭제
docker rmi $(docker images -q -f dangling=true)
# 시스템 전체 정리 (미사용 컨테이너, 이미지, 네트워크 등)
docker system prune -a
김개발 씨의 개발 서버 디스크가 90%나 차 있습니다. 어디에 공간이 사용되고 있는지 확인해보니 Docker가 상당 부분을 차지하고 있었습니다.
지난 몇 달간 테스트하면서 만들었던 컨테이너와 이미지가 쌓이고 쌓인 결과입니다. 박시니어 씨가 말합니다.
"Docker는 자동으로 청소해주지 않아. 직접 정리해줘야 해.
rm과 rmi 명령어를 알아두면 깔끔하게 관리할 수 있지." 그렇다면 docker rm과 docker rmi는 무엇이 다를까요? 쉽게 비유하자면, 붕어빵 틀과 붕어빵의 관계를 생각해보세요.
docker rm은 찍어낸 붕어빵(컨테이너)을 버리는 것이고, docker rmi는 붕어빵 틀(이미지) 자체를 버리는 것입니다. 붕어빵을 다 먹었으면 버리고, 더 이상 그 모양의 붕어빵을 만들 일이 없으면 틀도 버리는 것입니다.
정리하지 않으면 어떤 문제가 생길까요? 디스크 공간이 점점 줄어듭니다.
Docker 이미지는 보통 수백 MB에서 수 GB에 달합니다. 중지된 컨테이너도 파일 시스템 레이어를 유지하고 있어서 공간을 차지합니다.
어느 날 갑자기 "No space left on device" 에러를 만나게 됩니다. docker rm의 사용법을 살펴보겠습니다.
기본적으로 실행 중인 컨테이너는 삭제할 수 없습니다. 먼저 stop으로 중지한 뒤 rm으로 삭제해야 합니다.
하지만 -f 옵션을 사용하면 실행 중인 컨테이너도 강제로 삭제할 수 있습니다. 물론 데이터 손실이 발생할 수 있으니 주의해야 합니다.
여러 컨테이너를 한 번에 삭제하고 싶다면? **docker rm $(docker ps -aq -f status=exited)**를 사용합니다.
중지된 모든 컨테이너의 ID를 가져와서 한 번에 삭제합니다. docker rmi도 비슷합니다.
docker rmi nginx:latest는 nginx의 latest 태그 이미지를 삭제합니다. 단, 해당 이미지를 사용하는 컨테이너가 있으면 삭제되지 않습니다.
컨테이너를 먼저 삭제해야 합니다. 빌드 과정에서 생긴 dangling 이미지가 문제가 되기도 합니다.
이름과 태그가 없는 이미지들인데, docker images에서 **<none>**으로 표시됩니다. 이런 이미지는 **docker rmi $(docker images -q -f dangling=true)**로 정리할 수 있습니다.
가장 강력한 청소 명령어는 docker system prune입니다. 이 명령어는 중지된 컨테이너, 사용하지 않는 네트워크, dangling 이미지를 한 번에 삭제합니다.
-a 옵션을 추가하면 사용하지 않는 모든 이미지까지 삭제합니다. 한 번에 수 GB의 공간을 확보할 수 있습니다.
실제 현업에서는 어떻게 활용할까요? CI/CD 파이프라인에서 빌드할 때마다 이미지가 생성됩니다.
정기적으로 docker system prune을 실행하는 스크립트를 cron에 등록해두면 디스크 관리가 편해집니다. 개발 환경에서는 주 1회 정도 정리하는 것을 권장합니다.
하지만 주의할 점도 있습니다. 삭제는 되돌릴 수 없습니다.
볼륨에 저장하지 않은 데이터는 컨테이너와 함께 사라집니다. 또한 docker system prune -a는 현재 실행 중이지 않은 모든 이미지를 삭제하므로, 나중에 다시 다운로드해야 할 수 있습니다.
중요한 데이터가 있다면 반드시 백업 후 삭제하세요. 다시 김개발 씨의 이야기로 돌아가 봅시다.
docker system prune -a를 실행하자 15GB의 공간이 확보되었습니다. docker images로 확인하니 정말 필요한 이미지만 남았습니다.
"앞으로는 주기적으로 청소해야겠네요!" docker rm과 rmi는 컨테이너 환경을 깔끔하게 유지하는 필수 명령어입니다. 정기적인 청소로 쾌적한 개발 환경을 만드세요.
실전 팁
💡 - docker system prune은 강력하지만 위험할 수 있습니다. 항상 삭제 전 확인 메시지를 읽으세요
- --rm 옵션을 docker run에 추가하면 컨테이너 종료 시 자동 삭제됩니다
- 중요한 데이터는 반드시 볼륨에 저장하세요. 컨테이너 삭제 시 데이터도 사라집니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
백업 및 복구 전략 완벽 가이드
메일 서버와 중요 데이터를 안전하게 보호하는 백업 전략을 알아봅니다. Maildir 백업부터 증분 백업, 오프사이트 백업, 그리고 재해 복구 계획까지 실무에서 바로 적용할 수 있는 내용을 담았습니다.
Roundcube 웹메일 인터페이스 완벽 가이드
Docker 컨테이너 기반으로 Roundcube 웹메일을 구축하고, Nginx 리버스 프록시부터 플러그인 관리, 테마 커스터마이징까지 전체 과정을 다룹니다. 초급 개발자도 쉽게 따라할 수 있는 실무 중심 가이드입니다.
SSL/TLS 인증서 설정 완벽 가이드 (Let's Encrypt)
메일 서버 운영에 필수적인 SSL/TLS 인증서 설정 방법을 다룹니다. Let's Encrypt를 활용한 무료 인증서 발급부터 자동 갱신까지, 실무에서 바로 적용할 수 있는 내용을 담았습니다.
Dovecot으로 IMAP/POP3 메일 서버 구축하기
Linux 환경에서 Dovecot을 활용하여 IMAP과 POP3 메일 서버를 구성하는 방법을 다룹니다. 메일 저장소 설정부터 사용자 인증, 쿼터 관리까지 실무에서 필요한 핵심 설정을 단계별로 학습합니다.
SMTP 서버 구성 Postfix 완벽 가이드
리눅스 환경에서 Postfix를 활용한 메일 서버 구축의 모든 것을 다룹니다. 아키텍처 이해부터 보안 설정까지, 실무에서 바로 적용할 수 있는 핵심 내용을 담았습니다.