docker run default format
docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
--name
- 컨테이너를 제어할 경우 매번 컨테이너 id를 기억하기 어렵기에 해당 옵션을 통해 컨테이너에 이름을 부여해준다.
$ docker run --name test -d nginx:alpine 4bed76d3ad428b889c56c1ecc2bf2ed95cb08256db22dc5ef5863e1d03252a19
$docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4bed76d3ad42 nginx:alpine "/docker-entrypoint.…" 1 second ago Up Less than a second 80/tcp test
설정한 이름을 통해 stop, remove 등의 커맨드를 실행할 수 있다.
$ docker stop test
test
$ docker rm test
test
## -e
[Set environment variables](https://docs.docker.com/reference/cli/docker/container/run/#env)
- `-e`, `--env`, `--env-file`
- 컨테이너의 환경변수 설정
컨테이너를 실행할 때 아래와 같이 환경변수를 정의할 수 있다.
$ docker run --env VAR1=value1 --env VAR2=value2 ubuntu env | grep VAR
VAR1=value1
VAR2=value2
-e
Set environment variables
- `-e`, `--env`, `--env-file`
- 컨테이너의 환경변수 설정
컨테이너를 실행할 때 아래와 같이 환경변수를 정의할 수 있다.
export된 로컬 환경변수를 사용할 수 있다.
export VAR1=value1
export VAR2=value2
$ docker run --env VAR1 --env VAR2 ubuntu env | grep VAR
VAR1=value1
VAR2=value2
--env file
cat env.list
# This is a comment
VAR1=value1
VAR2=value2
USER
$ docker run --env-file env.list ubuntu env | grep -E 'VAR|USER'
VAR1=value1
VAR2=value2
USER= dev
포그라운드와 백그라운드
-d
- --detach와 동일
- 백그라운드에서 실행하기 위해 해당 옵션 사용
- 만약 해당 옵션 지정 안할 시 포그라운드에서 실행되기 때문에 cmd + c 등으로 터미널에서 컨테이너를 나갈 시 컨테이너는 종료된다.
$ docker run -d IMAGE
$ docker run -d nginx
0246aa4d1448a401cabd2ce8f242192b6e7af721527e48a810463366c7ff54f1
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0246aa4d1448 nginx "/docker-entrypoint.…" 2 seconds ago Up 1 second 80/tcp pedantic_liskov
docker logs -n 5 0246aa4d1448
2023/11/06 15:58:23 [notice] 1#1: start worker process 33
2023/11/06 15:58:23 [notice] 1#1: start worker process 34
2023/11/06 15:58:23 [notice] 1#1: start worker process 35
2023/11/06 15:58:23 [notice] 1#1: start worker process 36
2023/11/06 15:58:23 [notice] 1#1: start worker process 37
$ docker attach 0246aa4d1448
^C
2023/11/06 15:58:40 [notice] 1#1: signal 2 (SIGINT) received, exiting
...
다른 옵션들
docker run --detach
: run container in backgrounddocker run --attach
: attach tostdin
,stdout
, andstderr
docker run --tty
: allocate a pseudo-ttydocker run --interactive
: keepstdin
open even if not attached
-t
--tty
(-t
) 명령어는 TTY(pseudo-tty)를 연결하여, 사용자의 터미널을 컨테이너의 입력 / 출력 스트림에 연결할 수 있게 해준다. 컨테이너에 TTY를 할당하면 TTY 장치가 제공하는 입출력 기능을 사용할 수 있게 된다.
debian 컨테이너에서 passwd 명령어를 실행해 root 비밀번호를 설정하는 예제
$ docker run -i debian passwd root
New password: karjalanpiirakka9
Retype new password: karjalanpiirakka9
passwd: password updated successfully
위 명령은 -i
플래그만 사용했는데, 이는 컨테이너의 STDIN(표준 입력)에 텍스트를 보낼 수 있게 해준다.
하지만 이 경우 passwd
프롬프트는 비밀번호를 평문(plain text) 으로 출력
반면 -t
플래그도 함께 사용하면, 비밀번호가 숨겨진다.
docker run -it debian passwd root
New password:
Retype new password:
passwd: password updated successfully
이는 passwd
명령어가 TTY의 echo-off 기능을 사용해 입력되는 문자의 출력(echo)을 억제할 수 있기 때문이다.
-t
플래그는 -i
플래그 없이도 사용할 수 있다. 이 경우에도 컨테이너에 pseudo-tty가 할당되지만, STDIN에 텍스트를 보낼 수는 없다. 이러한 방식은 컨테이너의 출력이 TTY 환경을 필요로 할 때 유용할 수 있다.
-i
--interactive
(-i
) flag는 컨테이너의 STDIN(표준 입력)을 열어둔 상태로 유지시킨다.
사용자가 STIDIN을 통해서 컨테이너에 입력을 컨테이너에 보낼 수 있도록 해준다.
$ echo hello | docker run --rm -i busybox cat
hello
일반적으로 -i flag는 위에 나왔던 -t와 같이 사용되어 컨테이너의 입출력 스트림을 tty에 바인딩하고, 상호작용 가능한 터미널 세션을 생성할 수 있다.
$ docker run -it debian
root@10a3e71492b0:/# factor 90
90: 2 3 3 5
root@10a3e71492b0:/# exit
exit
-i flag만 단독 사용하면 입력을 pipe를 통해 컨테이너에 전달하는 식으로 활용할 수 있다.
$ docker run --rm -i busybox echo "foo bar baz" \
| docker run --rm -i busybox awk '{ print $2 }' \
| docker run --rm -i busybox rev
rab
-p
$ docker run -p 127.0.0.1:80:8080/tcp nginx:alpine
이 명령은 컨테이너의 8080번 포트를 호스트의 127.0.0.1 주소의 80번 TCP 포트에 바인딩합니다. tcp
외에도 udp
나 sctp
포트도 지정할 수 있습니다. Docker의 네트워킹 개요 문서에서는 포트 공개에 대한 자세한 설명이 있습니다.
주의 사항
포트 매핑 시 IP 주소를 명시하지 않으면 (예:-p 80:80
처럼127.0.0.1
없이) Docker는 기본적으로 모든 인터페이스(0.0.0.0
)에 포트를 공개한다. 이 경우 외부에서 해당 포트에 접근이 가능하게 된다.
이는 UFW 같은 방화벽에서 해당 포트를 차단하더라도 마찬가지인데, Docker가 자체적으로iptables
규칙을 관리하기 때문입니다. 자세한 내용은 Docker 공식 문서를 참고
$ docker run --expose 80 nginx:alpine
위 명령은 컨테이너의 80번 포트를 외부에 공개하지 않고, 내부적으로만 노출시킨다. 즉, 다른 컨테이너에서는 해당 포트로 접근할 수 있지만, 호스트 머신에서는 접근할 수 없다.
-v
$ docker run -v $(pwd):$(pwd) -w $(pwd) -i -t ubuntu pwd
위 명령은 현재 디렉터리를 컨테이너 안의 동일한 경로롤 마운트하고(-v), 해당 경로를 작업 디렉터리(-w)로 설정한 후, 컨테이너 안에서 pwd 명령어를 실행한 명령어다.
Docker engine v23 부터는 호스트의 상대경로도 사용할 수 있다.
$ docker run -v ./content:/content -w /content -i -t ubuntu pwd
이 예시는 현재 디렉토리의 ./content
디렉토리를 컨테이너의 /content
경로로 마운트하고, 그 디렉토리를 작업 디렉토리로 설정하여 pwd
명령어를 실행합니다.
$ docker run -v /doesnt/exist:/foo -w /foo -i- t ubuntu bash
위 예시에서 호스트 경로 /doesnt/exist
가 실제로 존재하지 않아도, Docker는 자동으로 해당 디렉토리를 생성해 컨테이너를 실행합니다.
읽기 전용 볼륨 마운트 (--read-only
)
$ docker run --read-only -v /icanwrite busybox touch /icanwrite/here
플래그를 사용하면 컨테이너의 루트 파일 시스템을 읽기 전용으로 마운트할 수 있다. 이 옵션은 컨테이너가 지정한 볼륨 이외의 경로에는 쓰기 작업을 하지 못하게 막는다. 위 예시는 /icanwrite
경로만 쓰기 가능하고 나머지는 읽기 전용이다
Docker 소켓을 마운트하여 호스트 Docker 제어
$ docker run -t -i -v /var/run/docker.sock:/var/run/docker.sock -v /path/to/static-docker-binary:/usr/bin/docker busybox sh
이 예시는 Docker 데몬 소켓과 정적 링크된 Docker 바이너리를 컨테이너에 바인드 마운트하여, 컨테이너에서 호스트의 Docker 데몬을 직접 제어할 수 있게 한다.
Windows에서 경로 지정
Windows에서는 Windows 스타일 경로(c:\path\to\dir
)를 사용해야 한다
PS C:\> docker run -v c:\foo:c:\dest microsoft/nanoserver cmd /s /c type c:\dest\somefile.txt
Contents of file
PS C:\> docker run -v c:\foo:d: microsoft/nanoserver cmd /s /c type d:\somefile.txt
Contents of file
📌 Windows 기반 컨테이너에서는 아래와 같은 마운트는 실패합니다
- 목적지가 기존에 내용이 있는 디렉토리인 경우
- 목적지가
C:
드라이브인 경우 - 원격 경로나 파일을 마운트하려고 할 때
ex)
net use z: \\remotemachine\share
docker run -v z:\foo:c:\dest ...
docker run -v \\uncpath\to\directory:c:\dest ...
docker run -v c:\foo\somefile.txt:c:\dest ...
docker run -v c:\foo:c: ...
docker run -v c:\foo:c:\existing-directory-with-contents ...
더 자세한 것은 공식문서 참고
-w
-w
옵션은 명령어를 지정한 디렉토리 안에서 실행되도록 한다.
만약 해당 경로가 컨테이너 안에 존재하지 않으면, Docker는 자동으로 그 디렉토리를 생성한다.
$ docker run -w /path/to/dir/ -i -t ubuntu pwd
예시에서는 /path/to/dir/
디렉토리에서 명령어가 실행된다.
-rm
기본적으로, 컨테이너가 종료되더라도 해당 컨테이너의 파일 시스템은 유지된다.
이렇게 하면 종료 후에도 컨테이너의 최종 상태를 확인하거나 데이터를 그대로 보존할 수 있어 디버깅에 유리
하지만 짧은 시간 동안 실행되는 일회성 작업이 많아지면, 이런 컨테이너 파일 시스템들이 쌓여 디스크 공간을 차지하게 된다.
이럴 경우, 컨테이너가 종료되면 자동으로 컨테이너와 그 파일 시스템을 삭제하려면 --rm
플래그를 사용할 수 있다
--rm
: 컨테이너 종료 시 자동으로 삭제
주의 사항
--rm
플래그를 설정하면, 컨테이너가 제거될 때 해당 컨테이너에 연결된 익명 볼륨(이름 없는 볼륨)도 함께 삭제
이는docker rm -v my-container
명령을 실행하는 것과 유사
단, 이름이 지정된 볼륨은 삭제되지 않는다.
ex)
$ docker run --rm -v /foo -v awesome:/bar busybox top
/foo
는 익명 볼륨이므로 컨테이너 종료 시 자동 삭제- 반면,
awesome:/bar
는 이름이 지정된 볼륨이므로 삭제되지 않는다.
또한, --volumes-from
으로 상속된 볼륨도 마찬가지로, 이름 없는 볼륨만 자동 삭제되며, 이름이 지정된 볼륨은 유지된다.
--entrypoint
이미지의 기본 ENTRYPOINT를 덮어 씌운다.
--cpus, --memory
CPU와 메모리 리소스를 제한
$ docker run --cpus="2" --memory="500m" ubuntu
CPU는 2개, 메모리는 500mb로 제한
--user
컨테이너에서 사용자/그룹 ID를 명시적으로 지정
$ docker run --user 1000:1000 ubuntu