docker run options

docker run은 컨테이너의 라이프사이클에서 create 와 start 를 합친 것과 같다. 즉, 컨테이너를 생성해서 바로 실행시키는 것이다.

따라서 Dockerfile 로 이미지를 만들었을 때, run 을 할 경우 이미지에서 설정했던 CMD 혹은 ENTRYPOINT를 실행시키며 컨테이너가 동작한다.


Options

옵션들 중 1개의 문자로만 이루어진 옵션들은 하나로 합쳐서 쓸 수 있다. 예를 들어 docker run -i -t 대신 docker run -it처럼 사용하는 것을 권장한다.

-i / -t

-i 옵션은 –interactive 와 같은데, 컨테이너의 표준입력과 표준출력을 활성화한다. 이 옵션만 줄 경우, 호스트의 표준 입력이 컨테이너로 들어가고, 컨테이너의 표준 출력이 호스트의 표준 출력으로 찍힌다.

그러나 -i 옵션 하나만 줄 경우에는, 그냥 컨테이너에서 실행된 배쉬쉘 프로그램에 입력을 넣으면 출력이 호스트OS에 찍힐 뿐이기 때문에 많이 아쉽다.

컨테이너에 서버 접속하듯이 접근하기 위해서는, 배쉬쉘에다가 유저와 컴퓨터가 텍스트를 주고 받는 인터페이스인 콘솔을 붙여줘야 하는데, 이를 위해 -t 옵션을 사용한다.

-t 옵션은 TTY 를 말하는데, tty 란 OS에서 제공하는 가상 콘솔로 커널에서 CLI 터미널을 에뮬레이팅한다.

그렇기 때문에 -it 옵션을 둘 다 줄 경우, 컨테이너에서 배쉬쉘이 실행되고, 콘솔이 붙어 터미널이 에뮬레이팅되고, 거기에 표준입출력이 붙어 서버에 ssh 접속한 것 마냥 사용할 수 있다.


-p (–publish) / -P (–publish-all)

-p 옵션은 호스트의 포트와 컨테이너의 포트를 매핑시켜서, 호스트의 특정 포트로 전달되는 데이터를 컨테이너의 포트로 포워딩시킬 수 있다.(vice versa)

컨테이너에 애플리케이션을 실행시키고 웹UI로 제공되는 서비스들을 확인할 때(주피터노트북, 웹앱, 하둡 등) 포워딩 시켜야 호스트의 웹브라우저에서 접근할 수 있다.

호스트와 컨테이너가 꼭 같은 포트로 매핑될 필요는 없다. 즉, 호스트의 5000번과 컨테이너의 6000번 포트가 연결될 수도 있다.

-p 호스트 포트:컨테이너 포트 처럼 사용한다.

도커 이미지를 만드는 Dockerfile에서 EXPOSE 구문을 통해 포트를 개방하겠다고 선언할 수 있는데, 이렇게 이미지를 만든다고 할지라도 실행시 p 옵션을 주어야 한다.

그러나 EXPOSE 된 포트에 대해서는 소문자가 아닌 대문자 옵션 -P 하나만 줌으로써 컨테이너의 해당 포트를 열 수 있다.

다만 이렇게 개방할 경우 호스트의 포트는 OS에서 남는 임의의 포트로 매핑시킨다는 것을 주의해야 한다.


-v (–volume)

-v 옵션은 컨테이너에 볼륨을 붙이는 것으로, 호스트 파일시스템에서의 특정 경로와 컨테이너 파일시스템에서의 특정 경로를 연결한다.

포트와 비슷하게 -v 호스트 경로:컨테이너 경로 처럼 지정해줄 수 있고, 이렇게 볼륨이 붙을 경우 컨테이너에서 해당 경로에 파일을 쓸 경우 그 파일이 호스트의 파일시스템에도 남게 된다.

컨테이너가 작업을 수행하고 종료될 경우, 그 안에서 생성되었던 파일들은 모두 사라지게 되는데 이 때 볼륨을 붙여놓고 해당 경로에서 작업을 했다면, 마운트시켰던 호스트의 파일시스템에 파일이 써진 것이기 때문에 사라지지 않는 것이다.

컨테이너를 생성할 때 파일시스템의 경로를 마운트시켜도 되지만, docker volume 명령어를 통해 미리 도커가 관리하는 볼륨을 생성해놓고 이를 활용할 수도 있다.


-e (–env)

컨테이너에 환경변수를 설정해줄 때는 -e 옵션을 통해 넘겨줄 수 있다(여러번 반복 사용 가능).

각종 애플리케이션에서는 환경 변수 값을 참조해서 동작하는 것들이 많은데, 예를 들어 JAVA_HOME이 대표적이다.

이런 환경변수들은 Dockerfile 에서 설정해주거나, 컨테이너가 실행될 때 내부적으로 쉘스크립트를 실행시켜 export 해줘도 적용이 안되는데, -e 옵션을 주던가 docker-compose 에서 설정해주는 방법밖에 없다(있는데 못 찾았을수도?).

아래처럼 -e 옵션 이후 한칸 띄거나, = 으로 붙이거나, 혹은 –env 처럼 롱옵션으로 다양하게 여러개를 넘겨줄 수 있다.

bconfiden2@dmlab-bear0:~$ sudo docker run -e HI=yes -e="FOO=hello" --env="TEST=world" ubuntu:20.04 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=99c2012d5f8c
HI=yes
FOO=hello
TEST=world
HOME=/root


-d (–detach)

-d 옵션은 도커 컨테이너를 백그라운드에서 실행시킨다.

컨테이너 안에서 실행되는 프로세스가 백그라운드가 아닌(애초에 이렇게 실행되면 컨테이너가 종료된다) 컨테이너 자체가 호스트OS에서 백그라운드로 실행된다는 것이다.

아래처럼 mysql 을 포어그라운드 프로세스로 실행시키면 컨테이너의 표준출력을 받아와 호스트에 뿌리게 되고, 이러면 호스트에서는 아무것도 할 수가 없다.

호스트에서 아무리 Ctrl + C 로 시그널을 보내도 컨테이너에 전달되는 것이 아니라 컨테이너의 프로세스가 중지되지 않기 때문이다.

bconfiden2@dmlab-bear0:~$ sudo docker run -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.7
2021-10-01 23:31:35+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.35-1debian10 started.
2021-10-01 23:31:35+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
...
Version: '5.7.35'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)

그러나 아래처럼 -d 옵션을 줘서 대몬으로 동작시키면 컨테이너가 백그라운드로 돌아가 터미널에 대한 제어를 다시 호스트OS가 가져올 수 있다.

그러나 이렇게 실행할 경우에는 애플리케이션 로그를 따로 확인해줘야 한다.

bconfiden2@dmlab-bear0:~$ sudo docker run -d -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.7
a7fdda9d4ab38adc8e405979ceb74ef06ae9c063d24aabf35274469a6649e4af


-w (–workdir)

-w 옵션은, 컨테이너의 기본 작업 디렉토리를 설정해주는 옵션으로, Dockerfile 에서 WORKDIR 설정을 덮어쓴다.

아래처럼, 원래 우분투 이미지의 기본 경로는 루트이지만 -w 옵션으로 경로를 지정해준 뒤 pwd 를 찍어보면 해당 경로로 설정되었음을 확인할 수 있다.

bconfiden2@dmlab-bear0:~$ sudo docker run ubuntu:20.04 pwd
/
bconfiden2@dmlab-bear0:~$ sudo docker run -w /var/log ubuntu:20.04 pwd
/var/log


–name, –hostname, –rm

이외에도 알아두면 좋은 옵션들이 있다.

--name 은 컨테이너 이름을 지정해줄 수 있다. 이 옵션을 사용하지 않을 시 도커에서 임의로 유명한 과학자들 이름을 붙여 컨테이너를 생성해준다.

이름을 지정할 경우 알아보기도 쉽고 컨테이너 관리가 편해지기 때문에 아래처럼 이름을 지정해주는 것이 좋다.

bconfiden2@dmlab-bear0:~$ sudo docker run --name bconfiden2 ubuntu:20.04
bconfiden2@dmlab-bear0:~$ sudo docker ps -a
CONTAINER ID   IMAGE          COMMAND   CREATED         STATUS                     PORTS     NAMES
f5c6e5db25b2   ubuntu:20.04   "bash"    4 seconds ago   Exited (0) 3 seconds ago             bconfiden2

--hostname은 컨테이너의 이름이 아니라, 컨테이너가 실행됐을 때 해당 컨테이너 내부에서의 호스트 이름을 지정해주는 옵션이다.

아래에서 보듯이, –hostname 으로 이름을 지정하니, 컨테이너에서 env 명령을 실행했을 때 나오는 환경변수들 중 $HOSTNAME 의 값이 해당 이름으로 설정되었다. 또한 컨테이너 자체의 이름을 설정한 것이 아니기 때문에 ps 를 확인했을 때 컨테이너 이름은 임의로 지정되었다.

bconfiden2@dmlab-bear0:~$ sudo docker run --hostname bconfiden2 ubuntu:20.04 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=bconfiden2
HOME=/root
bconfiden2@dmlab-bear0:~$ sudo docker ps -a
CONTAINER ID   IMAGE          COMMAND   CREATED          STATUS                      PORTS     NAMES
01be07502cd5   ubuntu:20.04   "env"     12 seconds ago   Exited (0) 11 seconds ago             vibrant_elbakyan

--rm 은 컨테이너가 종료될 때, 해당 컨테이너를 자동으로 docker rm 까지 해서 삭제시켜주는 옵션이다.

컨테이너를 일회성으로 사용할 때, 간단한 테스트를 진행할 때 종료된 컨테이너가 쌓이지 않아서 편리하다.

특히 –name 옵션을 줬던 컨테이너가 종료된 상태로 남아있을 경우 동일한 이름으로 다시 컨테이너를 실행시키면 에러가 나는데, 애초에 –rm 옵션을 줬으면 컨테이너가 종료상태로 남아있지 않고 바로 지워지기 때문에 테스트할 때 번거롭게 컨테이너를 지우고 생성할 필요가 없다.