도커 첫걸음 3편 — docker run 익히기: 설치 없이 DB·웹 서버·주피터를 한 줄로 띄우기
도커를 가장 많이 쓰는 방식은 남이 만든 이미지를 실행하는 것입니다. PostgreSQL을 설치 마법사 없이, nginx를 설정 파일 없이, 주피터를 파이썬 설치 없이 docker run 한 줄로 띄워 봅니다. -d, --name, -p, -v, -e, --rm 여섯 옵션의 뜻을 '빼면 무슨 일이 생기나'로 이해하고, 로그 보기·컨테이너 안에 들어가기·멈추고 지우기·디스크 정리까지 일상 명령을 정리합니다. 옵션을 켜고 끄며 명령어를 조립해 보는 빌더 위젯과 자주 만나는 에러 해결표를 담았습니다.
아직 도커를 설치하지 않았다면 2편을 먼저 보세요. docker run --rm hello-world가 성공하면 준비 완료입니다.
1. 가장 단순한 run부터
도커 명령의 기본 모양은 이렇습니다.
docker run의 구조
docker run[옵션들]이미지이름:태그[컨테이너 안에서 실행할 명령]
옵션 없이 가장 단순하게 실행해 봅시다. 가벼운 리눅스 배포판인 알파인(alpine)에게 인사를 시킵니다.
bash
docker run alpine echo"안녕, 도커"
처음이면 Unable to find image 'alpine:latest' locally라는 메시지와 함께 이미지를 내려받고, 곧바로 안녕, 도커를 출력한 뒤 끝납니다. 컨테이너는 안의 명령이 끝나면 함께 종료됩니다. echo는 한 번 출력하고 끝나니 컨테이너도 곧바로 멈춘 것입니다.
리눅스 안에 들어가서 둘러보고 싶다면 -it 옵션으로 대화형 셸을 엽니다.
bash
docker run -it --rm ubuntu:24.04 bash
프롬프트가 root@a1b2c3d4:/#처럼 바뀌면 컨테이너 안입니다. ls, cat /etc/os-release를 쳐 보세요. 내 맥이나 윈도우 안에서 우분투가 1초 만에 켜졌습니다. exit를 치면 나오고, --rm 덕분에 컨테이너는 자동으로 지워집니다.
💡
-it는 두 옵션의 합체입니다.-i(interactive)는 키보드 입력을 컨테이너로 보내고, -t(tty)는 터미널 화면을 붙여 줍니다. 셸처럼 사람이 대화하는 프로그램을 띄울 때는 거의 항상 -it를 같이 씁니다.
2. 서버를 띄우는 여섯 가지 옵션
echo처럼 끝나는 프로그램이 아니라, 웹 서버나 DB처럼 계속 켜져 있어야 하는 프로그램을 띄울 때는 옵션이 필요합니다. 거의 모든 경우에 이 여섯 개 안에서 해결됩니다.
컨테이너는 격리된 작은 컴퓨터라서, 그 안에서 80번 포트로 웹 서버가 돌아도 바깥에서는 보이지 않습니다.-p 8080:80은 "내 컴퓨터의 8080번으로 들어오는 요청을 컨테이너의 80번으로 보내라"는 통로를 뚫는 것입니다. 마찬가지로 컨테이너 안의 파일은 컨테이너가 사라지면 함께 사라지므로, 남겨야 할 데이터는 -v로 바깥에 연결해 둡니다.
⚠️
순서 규칙은 딱 하나 — "내 쪽 : 컨테이너 쪽".-p 8080:80은 내 8080 → 컨테이너 80, -v ./site:/usr/share/nginx/html은 내 ./site 폴더 → 컨테이너의 그 경로입니다. 왼쪽이 항상 바깥(나), 오른쪽이 안(컨테이너)입니다.
아래 빌더에서 옵션을 하나씩 켜고 끄면서 명령이 어떻게 바뀌는지, 빼면 무슨 일이 생기는지 확인해 보세요.
3. 실전 ① — 웹 서버(nginx)로 내 HTML 띄우기
빈 폴더를 하나 만들고 HTML 파일을 넣습니다.
bash
mkdir -p ~/docker-lab/site && cd ~/docker-lab
echo'<h1>도커로 띄운 첫 페이지</h1>' > site/index.html
nginx 컨테이너를 띄우면서 이 폴더를 nginx의 웹 루트에 연결합니다. :ro는 읽기 전용(read-only)이라는 뜻으로, 컨테이너가 내 파일을 고치지 못하게 합니다.
bash
docker run -d --name web -p 8080:80 -v ./site:/usr/share/nginx/html:ro nginx:1.29
브라우저에서 http://localhost:8080을 열어 보세요. 방금 만든 제목이 보입니다. 이제 site/index.html을 편집기로 고치고 새로고침하면 곧바로 반영됩니다. 폴더가 연결되어 있기 때문입니다. 개발할 때 도커를 쓰는 기본 원리가 이것입니다.
💡
윈도우 PowerShell이라면./site 대신 ${PWD}/site를 쓰세요. WSL2 우분투 터미널에서는 위 명령 그대로 됩니다. 옛날 도커 버전에서 ./ 상대 경로가 안 먹으면 "$(pwd)/site"처럼 절대 경로로 바꾸면 됩니다.
4. 실전 ② — PostgreSQL을 설치 없이
데이터베이스는 데이터가 남아야 하므로 볼륨이 필수입니다. 이번에는 폴더 대신 도커가 관리하는 이름 붙은 볼륨(pgdata)을 씁니다.
줄 끝의 \는 "다음 줄에 이어진다"는 뜻이라 그대로 복사해 붙여도 됩니다. (PowerShell에서는 \ 대신 백틱 `을 쓰거나 한 줄로 이어 쓰세요.)
DB가 떴는지 확인하고, 컨테이너 안의 psql로 접속해 봅니다.
bash
docker ps
docker exec -it my-db psql -U postgres
postgres=# 프롬프트가 보이면 성공입니다. SELECT version();을 쳐 보고 \q로 나옵니다. DBeaver나 DataGrip 같은 DB 도구에서는 호스트 localhost, 포트 5432, 사용자 postgres, 비밀번호 secret으로 접속하면 됩니다.
🔍
필요한 환경변수는 어디서 알까? Docker Hub의 이미지 페이지(예: hub.docker.com/_/postgres)에 "Environment Variables" 절이 있습니다. POSTGRES_PASSWORD는 필수, POSTGRES_USER·POSTGRES_DB는 선택이라고 적혀 있습니다. 모르는 이미지를 쓸 때는 항상 이 페이지부터 보세요.
살아남았다가 출력되면, 컨테이너는 사라졌지만 데이터는 볼륨에 살아 있다는 뜻입니다. 이것이 1편에서 말한 "냉장고"입니다.
⚠️
포트 충돌 주의. 이미 내 컴퓨터에 PostgreSQL이 설치되어 5432를 쓰고 있다면 port is already allocated 에러가 납니다. 이때는 왼쪽(내 쪽) 번호만 바꾸세요: -p 5433:5432. 컨테이너 쪽(오른쪽)은 이미지가 정한 번호라 바꾸면 안 됩니다.
5. 실전 ③ — 파이썬 설치 없이 주피터 노트북
데이터 분석을 배우는데 파이썬·아나콘다 설치에서 막히는 경우가 많습니다. 도커로는 이렇게 끝납니다.
출력 중 http://127.0.0.1:8888/lab?token=...로 시작하는 주소를 브라우저에 붙여 넣으면 주피터랩이 열립니다. work 폴더에 만든 노트북은 내 컴퓨터의 ~/docker-lab/notebooks에 저장되므로 컨테이너를 지워도 남습니다.
💡
이미지 주소에 quay.io가 붙은 이유. 주피터 프로젝트는 2023년부터 공식 이미지를 Docker Hub가 아니라 Red Hat의 레지스트리인 quay.io에 올립니다. 이미지 이름 앞에 주소가 붙으면 그 레지스트리에서 받는다는 뜻입니다(1편의 "이미지 이름 읽는 법").
6. 일상 명령 — 보고, 들어가고, 멈추고, 지우기
컨테이너를 띄운 다음에 쓰는 명령은 몇 개 안 됩니다. 이 표를 옆에 두고 쓰세요.
하고 싶은 일
명령
메모
실행 중인 컨테이너 보기
docker ps
멈춘 것까지: docker ps -a
로그 보기
docker logs web
실시간 따라가기: docker logs -f web (Ctrl+C로 빠져나옴, 컨테이너는 계속 돎)
컨테이너 안에서 명령 실행
docker exec -it web sh
bash가 있는 이미지는 bash. 알파인 계열은 sh만 있다
멈추기 / 다시 켜기
docker stop web / docker start web
stop은 삭제가 아니다. 컨테이너 안의 변경도 그대로
지우기
docker rm web
실행 중이면 docker rm -f web (멈추고 바로 삭제)
내 이미지 목록
docker images
지우기: docker rmi nginx:1.29
자원 사용량
docker stats
CPU·메모리를 실시간으로. Ctrl+C로 종료
상세 정보
docker inspect web
IP, 마운트, 환경변수 등 전부 (JSON)
실습한 것들을 정리합니다.
bash
docker rm -f web my-db jupyter
볼륨은 rm으로 지워지지 않습니다(그래서 데이터가 남았던 것입니다). 볼륨까지 지우려면 따로 지웁니다.
bash
docker volume ls
docker volume rm pgdata
7. 디스크 청소 — 도커가 용량을 먹는다면
도커를 한동안 쓰면 안 쓰는 이미지·멈춘 컨테이너·빌드 캐시가 쌓여 수십 GB가 되기도 합니다. 얼마나 쓰고 있는지 봅니다.
bash
docker system df
멈춘 컨테이너, 어디서도 안 쓰는 네트워크, 이름 없는 이미지, 빌드 캐시를 한 번에 정리합니다. 실행 중인 컨테이너와 볼륨은 건드리지 않습니다.
bash
docker system prune
⚠️
docker system prune -a --volumes는 신중하게.-a는 지금 컨테이너가 쓰지 않는 모든 이미지를, --volumes는 연결되지 않은 볼륨(=DB 데이터)까지 지웁니다. 다시 받으면 되는 이미지는 괜찮지만, 볼륨 속 데이터는 되돌릴 수 없습니다.
8. 자주 만나는 에러와 해결
에러 메시지 (일부)
원인
해결
Cannot connect to the Docker daemon
도커 도구가 꺼져 있다
OrbStack·Rancher Desktop 실행, 또는 colima start
port is already allocated
그 포트를 다른 프로그램(또는 다른 컨테이너)이 쓰고 있다
-p의 왼쪽 번호를 바꾼다. docker ps로 겹치는 컨테이너 확인
Conflict. The container name "/web" is already in use
같은 이름의 컨테이너가 (멈춘 채로) 남아 있다
docker rm -f web 후 다시 run
브라우저에서 접속이 안 됨
-p를 빼먹었거나 컨테이너 포트 번호가 틀렸다
docker ps의 PORTS 열에 0.0.0.0:8080->80/tcp가 있는지 확인
컨테이너가 켜지자마자 꺼짐 (Exited (1))
필수 환경변수 누락, 설정 오류
docker logs 이름으로 마지막 에러 확인 — 대부분 여기에 답이 있다
no matching manifest for linux/arm64
Apple 실리콘 맥인데 이미지가 x86(amd64)용만 있다
--platform linux/amd64를 붙여 에뮬레이션으로 실행 (4편에서 자세히)
toomanyrequests
Docker Hub 다운로드 한도 초과
docker login (2편 참고)
마치며
🧠
3편 요약
· docker run [옵션] 이미지:태그 — 옵션은 -d · --name · -p · -v · -e · --rm 여섯 개면 거의 다 된다
· -p와 -v는 내 쪽:컨테이너 쪽
· 데이터가 남아야 하면 볼륨. 컨테이너를 지워도 볼륨은 남는다
· 막히면 docker ps -a와 docker logs부터
· 용량 정리는 docker system df → docker system prune
지금까지는 남이 만든 이미지를 실행했습니다. 다음 편에서는 내 앱을 이미지로 만듭니다. Dockerfile 한 줄 한 줄의 의미, 빌드를 빠르게 만드는 줄 순서, 그리고 맥(ARM)과 서버(x86)를 모두 지원하는 이미지를 만드는 법을 다룹니다.