Docker run
docker run은 Docker 이미지로부터 새 컨테이너를 생성하고 실행하는 Docker CLI 명령으로, 공식 명령은 docker container run이며 docker run은 그 별칭으로 사용된다.[1]
docker run은 지정한 이미지로 컨테이너를 만들고, 필요한 경우 이미지를 레지스트리에서 가져온 뒤, 컨테이너의 기본 명령 또는 사용자가 지정한 명령을 실행한다. 로컬에 이미지가 없으면 기본적으로 이미지를 풀한 뒤 실행하며, 이미 정지된 컨테이너를 다시 실행하려면 docker start를 사용한다.[1]
기본 형식은 다음과 같다.
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
예를 들어 ubuntu:24.04 이미지로 일회성 셸을 실행하려면 다음과 같이 입력한다.
docker run --rm -it ubuntu:24.04 bash
docker run 명령은 크게 옵션, 이미지, 컨테이너 내부에서 실행할 명령으로 구성된다.
| 구성 요소 | 예시 | 설명 |
|---|---|---|
| 옵션 | --rm -it -v "$PWD":/app -p 8080:80
|
컨테이너 삭제, 터미널 연결, 볼륨 마운트, 포트 공개 등 실행 방식을 지정한다. |
| 이미지 | nginx:latest, ubuntu:24.04
|
컨테이너를 생성할 기준 이미지이다. 태그를 생략하면 일반적으로 latest 태그가 사용된다.
|
| 명령 | bash, npm start
|
이미지에 정의된 기본 명령 대신 컨테이너 안에서 실행할 명령이다. |
docker run [옵션] 이미지[:태그] [컨테이너_내부_명령]
아래 옵션들은 실무에서 사용 빈도가 높은 순서와 학습 중요도를 고려해 정리한 것이다.
| 순서 | 옵션 | 의미 | 대표 사용 상황 |
|---|---|---|---|
| 1 | --rm
|
컨테이너 종료 시 자동 삭제 | 테스트, 일회성 실행, 임시 셸 |
| 2 | -it
|
표준 입력 유지(-i)와 가상 터미널 할당(-t)
|
대화형 셸, 디버깅 |
| 3 | -v, --volume
|
호스트 경로 또는 Docker 볼륨을 컨테이너에 마운트 | 소스 코드 공유, 데이터 영속화 |
| 4 | -p, --publish
|
호스트 포트와 컨테이너 포트를 연결 | 웹 서버, API 서버 실행 |
| 5 | --name
|
컨테이너 이름 지정 | 컨테이너 식별, 로그 확인, 네트워크 연결 |
| 6 | -d, --detach
|
백그라운드 실행 | 서버 프로세스 실행 |
| 7 | -e, --env
|
환경 변수 전달 | 설정값, 비밀번호, 실행 모드 지정 |
| 8 | --env-file
|
파일에서 환경 변수 일괄 전달 | 환경별 설정 관리 |
| 9 | --network
|
컨테이너 네트워크 지정 | 컨테이너 간 통신, 네트워크 격리 |
| 10 | --restart
|
컨테이너 재시작 정책 지정 | 운영용 데몬, 장애 자동 복구 |
| 11 | -w, --workdir
|
컨테이너 내부 작업 디렉터리 지정 | 소스 디렉터리 기준 명령 실행 |
| 12 | -u, --user
|
컨테이너 내부 실행 사용자 지정 | 루트 권한 회피, 파일 권한 관리 |
| 13 | --entrypoint
|
이미지의 기본 엔트리포인트 재정의 | 디버깅, 초기화 명령 우회 |
| 14 | --pull
|
이미지 풀 정책 지정 | 최신 이미지 보장, CI/CD |
| 15 | --platform
|
실행 플랫폼 지정 | ARM, AMD64 이미지 선택 |
| 16 | --cpus, --memory
|
CPU와 메모리 제한 | 리소스 제어, 테스트 환경 제한 |
| 17 | --mount
|
구조화된 마운트 옵션 | 복잡한 바인드 마운트, 볼륨 마운트 |
| 18 | --add-host
|
컨테이너 내부 /etc/hosts 항목 추가
|
로컬 도메인 테스트, 내부 이름 해석 |
| 19 | --privileged
|
확장된 권한 부여 | 특수 장치 접근, Docker-in-Docker 등 제한적 상황 |
| 20 | --cap-add, --cap-drop
|
Linux capability 추가 또는 제거 | 최소 권한 원칙 적용 |
--rm은 컨테이너가 종료될 때 컨테이너 파일 시스템을 자동으로 삭제한다. 테스트용 컨테이너나 일회성 명령 실행에 적합하다.[1]
docker run --rm hello-world
임시 Ubuntu 셸을 열고, 종료하면 컨테이너를 남기지 않는다.
docker run --rm -it ubuntu:24.04 bash
Python 스크립트를 임시 컨테이너에서 실행한다.
docker run --rm -v "$PWD":/app -w /app python:3.12 python app.py
--rm은 컨테이너를 남기지 않기 때문에 실행 후 로그나 파일 시스템 상태를 조사해야 하는 경우에는 사용하지 않는 편이 낫다.
-it는 -i와 -t를 함께 쓴 축약형이다. -i는 표준 입력을 열어 두고, -t는 가상 터미널을 할당한다. 보통 컨테이너 안에서 셸을 열 때 함께 사용한다.[1]
docker run --rm -it ubuntu:24.04 bash
Alpine Linux에서 셸을 실행한다.
docker run --rm -it alpine:latest sh
실행 중인 컨테이너에 들어가는 명령은 docker run이 아니라 docker exec를 사용한다.
docker exec -it my-nginx sh
-v 또는 --volume은 호스트의 디렉터리, 파일, 또는 Docker 볼륨을 컨테이너 내부 경로에 마운트한다. 짧고 자주 쓰이지만, 복잡한 설정에는 --mount가 더 명시적이다.[2][3]
현재 디렉터리를 컨테이너의 /app에 마운트한다.
docker run --rm -it -v "$PWD":/app -w /app node:22 bash
컨테이너 안에서 호스트 파일을 읽는다.
docker run --rm -v "$PWD":/app -w /app alpine:latest ls -al
읽기 전용으로 마운트한다.
docker run --rm -v "$PWD":/app:ro -w /app alpine:latest cat README.md
Docker 볼륨을 사용해 데이터베이스 데이터를 보존한다.
docker volume create mysql-data
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-v mysql-data:/var/lib/mysql \
mysql:8.4
바인드 마운트와 볼륨 마운트의 차이는 다음과 같다.
| 구분 | 예시 | 특징 |
|---|---|---|
| 바인드 마운트 | -v "$PWD":/app
|
호스트의 실제 경로를 컨테이너에 연결한다. 개발 환경에서 소스 코드를 공유할 때 많이 쓴다. |
| Docker 볼륨 | -v mysql-data:/var/lib/mysql
|
Docker가 관리하는 저장 공간을 연결한다. 데이터베이스 데이터처럼 영속성이 필요한 데이터에 적합하다. |
-p 또는 --publish는 호스트 포트를 컨테이너 포트에 매핑한다. 컨테이너 내부 서비스는 기본적으로 호스트 외부에서 직접 접근할 수 없으므로, 웹 서버나 API 서버를 테스트할 때 자주 사용한다.[4]
Nginx 컨테이너의 80번 포트를 호스트 8080번 포트로 연결한다.
docker run --rm -d --name web -p 8080:80 nginx:latest
브라우저 또는 curl로 접근한다.
curl http://localhost:8080
호스트의 특정 IP에만 바인딩할 수도 있다.
docker run --rm -d --name web -p 127.0.0.1:8080:80 nginx:latest
여러 포트를 동시에 공개한다.
docker run --rm -d \
--name app \
-p 8080:8080 \
-p 8443:8443 \
my-app:latest
--name은 컨테이너 이름을 지정한다. 이름을 지정하지 않으면 Docker가 임의의 이름을 부여한다. 운영이나 디버깅에서는 명시적인 이름을 붙이는 것이 편리하다.[1]
docker run -d --name my-nginx -p 8080:80 nginx:latest
이름으로 로그를 확인한다.
docker logs my-nginx
이름으로 컨테이너를 정지하고 삭제한다.
docker stop my-nginx
docker rm my-nginx
같은 이름의 컨테이너가 이미 있으면 새 컨테이너를 만들 수 없으므로, 기존 컨테이너를 삭제하거나 다른 이름을 사용해야 한다.
-d 또는 --detach는 컨테이너를 백그라운드에서 실행하고 컨테이너 ID를 출력한다. 서버 프로세스처럼 계속 실행되는 컨테이너에 많이 사용한다.[1]
docker run -d --name redis redis:7
실행 상태를 확인한다.
docker ps
로그를 실시간으로 확인한다.
docker logs -f redis
-e 또는 --env는 컨테이너에 환경 변수를 전달한다. 애플리케이션 설정, 데이터베이스 비밀번호, 실행 모드 등을 지정할 때 사용한다.[1]
docker run --rm -e NODE_ENV=production node:22 node -e "console.log(process.env.NODE_ENV)"
MySQL 컨테이너에 루트 비밀번호와 데이터베이스 이름을 전달한다.
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=appdb \
mysql:8.4
호스트의 환경 변수 값을 그대로 전달할 수도 있다.
export APP_MODE=dev
docker run --rm -e APP_MODE alpine:latest env
비밀번호나 토큰을 명령행에 직접 쓰면 셸 히스토리나 프로세스 목록에 노출될 수 있으므로 운영 환경에서는 별도 보안 관리 방식을 고려해야 한다.
--env-file은 환경 변수 파일을 컨테이너에 전달한다. 환경 변수가 많거나 환경별 설정 파일을 분리하고 싶을 때 유용하다.[1]
cat > .env <<'EOF'
APP_ENV=local
APP_PORT=8080
DATABASE_URL=mysql://user:pass@db:3306/app
EOF
docker run --rm --env-file .env alpine:latest env
--network는 컨테이너가 사용할 네트워크를 지정한다. 기본값은 일반적으로 bridge 네트워크이며, 사용자 정의 브리지 네트워크를 만들면 컨테이너 이름으로 서로 통신하기 쉽다.[4]
사용자 정의 네트워크를 만든다.
docker network create app-net
MySQL 컨테이너를 해당 네트워크에서 실행한다.
docker run -d \
--name db \
--network app-net \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.4
애플리케이션 컨테이너에서 db라는 이름으로 데이터베이스에 접근한다.
docker run --rm \
--network app-net \
alpine:latest \
sh -c "apk add --no-cache mysql-client && mysql -h db -uroot -psecret -e 'SELECT 1'"
호스트 네트워크를 직접 사용하는 예시는 다음과 같다. 단, host 네트워크는 격리 수준과 플랫폼별 동작 차이를 고려해야 한다.
docker run --rm --network host nginx:latest
--restart는 컨테이너 종료 시 재시작 정책을 지정한다. 장시간 실행되는 서비스에 사용하지만, 일회성 컨테이너에는 보통 사용하지 않는다.[1]
항상 재시작하도록 실행한다.
docker run -d \
--name redis \
--restart unless-stopped \
redis:7
주요 값은 다음과 같다.
| 값 | 설명 |
|---|---|
no
|
자동 재시작하지 않는다. 기본값이다. |
on-failure
|
비정상 종료 시 재시작한다. |
always
|
컨테이너가 종료되면 항상 재시작한다. |
unless-stopped
|
사용자가 직접 정지하지 않은 경우 재시작한다. |
-w 또는 --workdir는 컨테이너 내부의 작업 디렉터리를 지정한다.[1]
docker run --rm \
-v "$PWD":/app \
-w /app \
python:3.12 \
python main.py
Node.js 프로젝트에서 현재 디렉터리를 마운트하고 의존성을 설치한다.
docker run --rm -it \
-v "$PWD":/app \
-w /app \
node:22 \
npm install
-u 또는 --user는 컨테이너 내부 프로세스를 특정 사용자나 UID/GID로 실행한다. 바인드 마운트한 디렉터리에 루트 소유 파일이 생기는 문제를 줄일 때 유용하다.[1]
현재 호스트 사용자의 UID/GID로 실행한다.
docker run --rm \
-u "$(id -u):$(id -g)" \
-v "$PWD":/app \
-w /app \
node:22 \
npm test
컨테이너 내부의 node 사용자로 실행한다.
docker run --rm -u node node:22 node -e "console.log(process.getuid())"
--entrypoint는 이미지에 정의된 기본 엔트리포인트를 재정의한다. 컨테이너가 즉시 종료되거나 기본 실행 명령을 우회해 디버깅해야 할 때 사용한다.[1]
이미지의 기본 엔트리포인트 대신 셸을 실행한다.
docker run --rm -it --entrypoint sh nginx:latest
엔트리포인트를 python으로 바꾸고 버전을 확인한다.
docker run --rm --entrypoint python python:3.12 --version
--pull은 컨테이너 실행 전에 이미지를 어떻게 가져올지 지정한다. CI/CD 환경에서는 최신 이미지를 보장하기 위해 --pull always를 쓰는 경우가 있다.[1]
docker run --rm --pull always alpine:latest cat /etc/os-release
주요 값은 다음과 같다.
| 값 | 설명 |
|---|---|
missing
|
로컬에 이미지가 없을 때만 가져온다. |
always
|
실행할 때마다 레지스트리에서 이미지를 확인하고 가져온다. |
never
|
이미지를 가져오지 않고 로컬 이미지로만 실행한다. |
--platform은 실행할 이미지의 플랫폼을 지정한다. 멀티 아키텍처 이미지를 사용할 때 linux/amd64, linux/arm64 등을 명시할 수 있다.[1]
docker run --rm --platform linux/amd64 alpine:latest uname -m
Apple Silicon 환경에서 AMD64 이미지를 테스트하는 예시는 다음과 같다.
docker run --rm --platform linux/amd64 node:22 node -p "process.arch"
--cpus와 --memory는 컨테이너가 사용할 수 있는 CPU와 메모리를 제한한다. 리소스 사용량을 제어하거나 장애 상황을 재현할 때 유용하다.[5]
CPU 1개, 메모리 512MiB로 제한한다.
docker run --rm \
--cpus="1.0" \
--memory="512m" \
nginx:latest
메모리 제한을 걸고 Node.js 스크립트를 실행한다.
docker run --rm \
--memory="256m" \
node:22 \
node -e "console.log('memory limited container')"
--mount는 마운트 타입과 옵션을 명시적으로 지정하는 방식이다. -v보다 길지만, 복잡한 마운트 설정을 읽기 쉽게 표현할 수 있다.[3]
바인드 마운트 예시:
docker run --rm \
--mount type=bind,source="$PWD",target=/app,readonly \
-w /app \
alpine:latest \
ls -al
Docker 볼륨 마운트 예시:
docker volume create app-cache
docker run --rm \
--mount type=volume,source=app-cache,target=/cache \
alpine:latest \
sh -c "echo cached > /cache/test.txt && cat /cache/test.txt"
--add-host는 컨테이너 내부의 /etc/hosts에 호스트명과 IP 주소를 추가한다. 로컬 개발 환경에서 임시 도메인 이름을 테스트할 때 유용하다.[1]
docker run --rm \
--add-host api.local:127.0.0.1 \
alpine:latest \
cat /etc/hosts
Docker Desktop 등 일부 환경에서는 호스트 머신을 가리키는 이름으로 host.docker.internal을 사용하는 경우가 많다.
docker run --rm \
--add-host host.docker.internal:host-gateway \
alpine:latest \
ping -c 1 host.docker.internal
--privileged는 컨테이너에 확장된 권한을 부여한다. 장치 접근, 커널 기능 사용, Docker-in-Docker 같은 특수한 경우에 쓰이지만 보안 위험이 크므로 일반 애플리케이션 컨테이너에는 사용하지 않는 것이 좋다.[1]
docker run --rm -it --privileged alpine:latest sh
운영 환경에서는 --privileged 대신 필요한 capability나 장치만 제한적으로 부여하는 방식을 우선 검토한다.
--cap-add와 --cap-drop은 컨테이너의 Linux capability를 추가하거나 제거한다. 최소 권한 원칙을 적용할 때 사용한다.[1]
모든 capability를 제거하고 필요한 권한만 추가하는 예시는 다음과 같다.
docker run --rm \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
nginx:latest
네트워크 진단 도구 사용을 위해 NET_ADMIN을 추가하는 예시는 다음과 같다.
docker run --rm -it \
--cap-add NET_ADMIN \
nicolaka/netshoot
컨테이너를 남기지 않고 명령만 실행한다.
docker run --rm alpine:latest echo "hello docker"
현재 날짜를 컨테이너 안에서 출력한다.
docker run --rm alpine:latest date
Ubuntu 컨테이너 안에서 셸을 연다.
docker run --rm -it ubuntu:24.04 bash
Alpine 컨테이너 안에서 셸을 연다.
docker run --rm -it alpine:latest sh
현재 디렉터리를 컨테이너에 마운트하고 Python 파일을 실행한다.
docker run --rm \
-v "$PWD":/app \
-w /app \
python:3.12 \
python main.py
패키지를 설치하고 테스트를 실행한다.
docker run --rm \
-v "$PWD":/app \
-w /app \
python:3.12 \
sh -c "pip install -r requirements.txt && pytest"
현재 디렉터리를 마운트하고 Node.js 명령을 실행한다.
docker run --rm -it \
-v "$PWD":/app \
-w /app \
node:22 \
npm install
테스트를 실행한다.
docker run --rm \
-v "$PWD":/app \
-w /app \
node:22 \
npm test
개발 서버를 실행하고 포트를 연결한다.
docker run --rm -it \
-v "$PWD":/app \
-w /app \
-p 3000:3000 \
node:22 \
npm run dev
Nginx를 백그라운드로 실행하고 호스트 8080번 포트로 공개한다.
docker run -d \
--name web \
-p 8080:80 \
nginx:latest
정적 파일을 Nginx 기본 경로에 읽기 전용으로 마운트한다.
docker run --rm -d \
--name static-web \
-p 8080:80 \
-v "$PWD/html":/usr/share/nginx/html:ro \
nginx:latest
로그를 확인한다.
docker logs -f static-web
MySQL 컨테이너를 실행하고 데이터를 Docker 볼륨에 저장한다.
docker volume create mysql-data
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=appdb \
-v mysql-data:/var/lib/mysql \
-p 3306:3306 \
mysql:8.4
MySQL 클라이언트 컨테이너로 접속한다.
docker run --rm -it \
--network container:mysql \
mysql:8.4 \
mysql -h 127.0.0.1 -uroot -psecret appdb
Redis를 백그라운드로 실행한다.
docker run -d \
--name redis \
-p 6379:6379 \
redis:7
Redis CLI로 접속한다.
docker run --rm -it \
--network container:redis \
redis:7 \
redis-cli -h 127.0.0.1
사용자 정의 네트워크를 만들고 애플리케이션과 데이터베이스를 같은 네트워크에 배치한다.
docker network create app-net
docker run -d \
--name db \
--network app-net \
-e POSTGRES_PASSWORD=secret \
postgres:16
docker run --rm -it \
--name app \
--network app-net \
-e DATABASE_HOST=db \
alpine:latest \
sh
사용자 정의 네트워크에서는 같은 네트워크에 속한 컨테이너가 컨테이너 이름으로 서로를 찾을 수 있다.
호스트에 Go를 설치하지 않고 Go 테스트를 실행한다.
docker run --rm \
-v "$PWD":/src \
-w /src \
golang:1.23 \
go test ./...
호스트에 Maven을 설치하지 않고 Java 프로젝트를 빌드한다.
docker run --rm \
-v "$PWD":/workspace \
-w /workspace \
maven:3.9-eclipse-temurin-21 \
mvn test
바인드 마운트한 디렉터리에 루트 소유 파일이 생기지 않도록 현재 사용자 UID/GID로 실행한다.
docker run --rm \
-u "$(id -u):$(id -g)" \
-v "$PWD":/app \
-w /app \
node:22 \
npm install
이미지의 기본 명령 대신 셸을 실행한다.
docker run --rm -it --entrypoint sh nginx:latest
컨테이너의 환경을 확인한다.
docker run --rm --entrypoint env nginx:latest
| 목적 | 명령 예시 |
|---|---|
| 임시 셸 | docker run --rm -it ubuntu:24.04 bash
|
| 현재 디렉터리 마운트 | docker run --rm -v "$PWD":/app -w /app alpine ls
|
| 웹 서버 실행 | docker run -d --name web -p 8080:80 nginx
|
| 환경 변수 전달 | docker run --rm -e APP_ENV=dev alpine env
|
| 볼륨으로 데이터 보존 | docker run -d -v mysql-data:/var/lib/mysql mysql:8.4
|
| 사용자 정의 네트워크 사용 | docker run --network app-net --name app my-app
|
| 현재 사용자 권한으로 실행 | docker run --rm -u "$(id -u):$(id -g)" -v "$PWD":/app image command
|
| 최신 이미지 확인 후 실행 | docker run --rm --pull always alpine
|
docker run은 새 컨테이너를 생성한다. 기존 컨테이너를 다시 시작하려면docker start를 사용한다.--rm을 사용하면 컨테이너 종료 후 컨테이너 자체가 삭제되므로, 종료 후 상태 분석이 필요한 경우에는 사용하지 않는다.- 바인드 마운트는 호스트 파일 시스템을 컨테이너에 노출하므로 경로와 권한을 신중히 지정해야 한다.
- 데이터베이스처럼 데이터 보존이 필요한 컨테이너는 컨테이너 내부 파일 시스템에만 의존하지 말고 Docker 볼륨을 사용한다.
-p 8080:80에서 앞의8080은 호스트 포트, 뒤의80은 컨테이너 포트이다.latest태그는 항상 같은 이미지를 의미하지 않을 수 있으므로 운영 환경에서는 명시적인 버전 태그를 사용하는 것이 좋다.--privileged는 컨테이너 격리를 크게 약화할 수 있으므로 필요한 경우에만 제한적으로 사용한다.- 민감한 값을
-e PASSWORD=...형태로 명령행에 직접 넣으면 기록에 남을 수 있으므로 운영 환경에서는 보안 저장소나 오케스트레이션 도구의 시크릿 기능을 고려한다.
| 명령어 | 설명 |
|---|---|
docker ps
|
실행 중인 컨테이너 목록을 확인한다. |
docker ps -a
|
정지된 컨테이너를 포함해 모든 컨테이너 목록을 확인한다. |
docker logs
|
컨테이너 로그를 확인한다. |
docker exec
|
실행 중인 컨테이너 안에서 새 명령을 실행한다. |
docker stop
|
실행 중인 컨테이너를 정지한다. |
docker start
|
정지된 컨테이너를 다시 시작한다. |
docker rm
|
정지된 컨테이너를 삭제한다. |
docker volume
|
Docker 볼륨을 생성, 조회, 삭제한다. |
docker network
|
Docker 네트워크를 생성, 조회, 삭제한다. |
- ↑ 1.00 1.01 1.02 1.03 1.04 1.05 1.06 1.07 1.08 1.09 1.10 1.11 1.12 1.13 1.14 1.15 1.16 Docker Docs, "docker container run", https://docs.docker.com/reference/cli/docker/container/run/, 확인일: 2026-06-26.
- ↑ Docker Docs, "Storage", https://docs.docker.com/engine/storage/, 확인일: 2026-06-26.
- ↑ 3.0 3.1 Docker Docs, "Bind mounts", https://docs.docker.com/engine/storage/bind-mounts/, 확인일: 2026-06-26.
- ↑ 4.0 4.1 Docker Docs, "Networking overview", https://docs.docker.com/engine/network/, 확인일: 2026-06-26.
- ↑ Docker Docs, "Runtime options with Memory, CPUs, and GPUs", https://docs.docker.com/engine/containers/resource_constraints/, 확인일: 2026-06-26.
