docker container run 명령 개요

docker container run 구문은 도커에서 가장 중요하고 기능이 많아서, 따로 한 페이지로 떼어 두었다. 사실상 가장 핵심적인 내용이다. 이 run 명령어는 pull, create, start 3가지를 모두 수행한다. 그래서 이미지가 없이 run을 수행하면 이미지를 받고, 컨테이너를 생성하고, 시작도 수행한다. 시작하면서 명시한 명령도 수행한다. 

docker container(안써도됨) run [옵션] 도커이미지명[:태그] [명령어]

이 명령의 옵션은 크게 4가지로 나뉜다. 그 설정은 다음과 같다.

 

  • 컨테이너 설정 옵션

  • 네트워크 설정 옵션

  • 환경변수 설정 옵션

  • 자원제한 설정 옵션

또한 도커 서버가 아닌 도커 서버-클라이언트로 구성된 경우(즉, 서버는 따로 있고 내가 명령어 치는 곳이 클라이언트인 경, 클라이언트에서 docker run 을 수행하면, 도커 서버의 docker daemon에 의해 실행되며, 결과를 클라이언트가 받아서 볼 수 있다.

 

컨테이너 설정 옵션

attach, -a

표준입력, 표준출력, 표준오류출력에 어태치한다.

--cidfile

컨테이너 아이디를 파일로 출력한다.

--detach, -d

컨테이너를 생성하고 백그라운드에서 작동시킨다. 보통 많이 쓴다. 

--interactive, -i

컨테이너의 표준 입력을 연다.

--tty, -t

단말기 디바이스를 사용한다.

--name

컨테이너의 이름을 만든다. 안쓰면, 랜덤으로 생성된다.

--user, -u

사용자명을 지정

--restart=[옵션]

명령의 실행 결과에 따라 재시작을 하는 옵션

no : 재시작하지 않음

on-failure : 종료 스테이터스가 0이 아닐 때 재시작한다.

on-failure:횟수n : 종료 스테이터스가 0이 아닐 때 n번 재시작한다.

always : 항상 재시작한다. (exit로 나가도, 재시작한다)

unless-stopped : 최근 컨테이너가 정지 상태가 아니라면 항상 재시작한다.

--rm

명령 실행 완료 후에 컨테이너를 자동 삭제 (--restart 옵션과 함께 사용할 수 없음)

 

# 참고 : 컨테이너의 "종료"
대부분의 컨테이너는 명령어에 /bin/bash를 넣으면, 해당 컨테이너에 진입할 수 있다. 컨테이너 진입한 후, exit를 입력하면 쉘에서 나가는게 아니고, 컨테이너를 "종료" 한다. 컨테이너에 인수를 넣으면, 그 인수를 "가진" 컨테이너로써 생성된다. 원래 컨테이너는 인수 없이 컨테이너에 구축된 내용 그대로 사용한다. 하지만 필요한 경우와 여러가지 사용을 위해 인수(명령어)를 추가하여 컨테이너를 실행한다. 컨테이너를 종료하지 않으려면, ctrl+p+q를 입력하여 빠져나올 수 있다.

 

docker container run centos

아무 일도 없이 컨테이너가 종료된다. 받은 인수가 없어 할 일이 없기 때문이다.

 

docker container run -itd centos

컨테이너가 백그라운드로 작동하고, 표준 입력 터미널이 열린 상태가 된다. 컨테이너가 계속 유지된다.

 

docker container run centos /bin/cal

아래와 같이 결과가 나오며 컨테이너가 종료된다. 받은 인수의 결과를 리턴하고 더이상 할 일이 없기 때문이다.

 

docker container run -itd centos /bin/cal

아무 결과도 없이 컨테이너가 종료된다. 백그라운드에서 /bin/cal을 실행하고 종료되었기 때문이다.

 

docker container run -it centos /bin/ping localhost

컨테이너로 진입 후 계속 핑을 날리게 된다. 끝없이.

ctrl+p+q로 빠져 나가면 이것은 백그라운드로 계속 ping을 날리는 중이다. 컨테이너는 살아있다.

만약 ctrl+p+q로 빠져 나가지 않고 exit로 나갔다면, 해당 명령이 끝나므로 컨테이너는 종료된다. 

 

 

네트워크 설정 옵션

포트 번호같은 네트워크 설정을 통해 외부에서 컨테이너의 프로세스에 액세스하도록 설정할 수 있고, 컨테이너끼리 통신도 할 수 있는 여러가지 네트워크 통신을 설정할 수 있다.

--add-host=[호스트명:ip주소]

컨테이너의 /etc/hosts 에 호스트명과 ip 정의

--dns=[ip주소]

컨테이너용 dns서버의 ip주소 지정

--expose

지정된 범위의 포트 번호를 할당
호스트OS까지만 해당 컨테이너의 포트를 노출한다. (외부에는 노출하지 않음)
expose한 포트는 호스트에서만 연결이 된다.
호스트에서만 쓸 목적으로 사용하는것이며 서비스로는 사용하지 않는다.

--mac-address=[맥주소]

컨테이너의 맥주소 지정

--net=[bridge | none | container:<이름 | id> | host | NETWORK]

컨테이너의 네트워크를 지정. 도커에서는 기본적으로 호스트os와 브릿지 연결을 하며, --net옵션을 통해 네트워크 설정 가능

- bridge : 브리지연결 사용 (default)

- none : 네트워크 연결하지 않음

- container:[이름 | id] 다른 컨테이너의 네트워크를 사용 (해당 컨테이너의 네트워크 기법을 그대로 사용하겠다는 의미.)

- host : 컨테이너가 호스트 os의 네트워크를 사용

- NETWORK : 사용자 정의 네트워크를 사용

--hostname, -h

컨테이너 자신의 호스트명을 지정

--publish, -p [호스트의포트번호]:[컨테이너포트번호]

호스트포트와 컨테이너포트를 매핑. 명시한 포트에 대한 액세스를 허가하기 위해 사용된다.
(-p 80:80 이라고 하면, 80번 포트에 대한 액세스를 허가)
호스트os를 넘어 외부에 포트를 오픈한다.

둘이 되도록이면 같은 포트는 피해야 한다. -p 1521:1523 이런식으로.
-p  80 이렇게 하나만 있으면 컨테이너의 포트이다. 호스트포트는 알아서 지정하라는뜻.

docker ps에서 의미 예시
 -p 8080:80 옵션으로 하면 다음과 같이 docker ps에서 확인할 수 있다.
0.0.0.0:8080->80/tcp
 : 컨테이너 80/tcp가 호스트 0.0.0.0:8080에 연결된 것. 
즉, 외부에서 도커 호스트의 8080 포트로 요청이 들어오면, 컨테이너의 80번 포트로 해당 요청을 forword.
--publish-all, -P 호스트의 임의의 포트를 컨테이너에 할당. 호스트os를 넘어 외부에 포트를 오픈한다.
알아서 32767번부터 포트를 임의로 넣어준다. 아무옵션없이 대문자P 로 옵션을 넣기만 하면 됨

 

예시 : 포트 설정

docker container run -d -p 8080:80 nginx

- nginx라는 이미지를 바탕으로 컨테이너를 생성하고, 백그라운드에서 실행한다. 그리고 호스트 포트 8080과 컨테이너포트 80을 매핑한다. (0.0.0.0:8080->80/tcp)

- 즉 이 명령을 실행하여 컨테이너를 만든 후, 브라우저 등에서 호스트의 8080에 엑세스하면 컨테이너에서 작동하고 있는 nginx(80번포트) 서비스에 엑세스할수 있다.

 

예시 : dns 서버 설정

docker container run -d --dns 192.168.1.1 nginx

 

예시 : 맥주소 설정

docker container run -d --mac-address="92:d0:c6:0a:29:33" centos

- docker container inspect --format="{{ .Config.MacAddress }} 로 실제 설정값 확인 가능

 

 

예시 : /etc/hosts 호스트명과 ip주소 정의하기

docker container run -it --add-host test.com:192.168.1.1 centos

 

예시 : 컨테이너 호스트명 설정

docker container run -it --hostname www.test.com

- 이 값은 자신의 /etc/hosts에도 자동으로 적용된다.

 

 

예시 : 도커 네트워크 명시하여 연결

docker container run -itd --name=webap --net=web-network nginx

- nginx 이미지이고 이름이 webap인 컨테이너를 web-network라는 도커 네트워크에 연결한다.

 

 

 

서버 환경설정 옵션

해당 컨테이너 OS의 환경설정을 컨테이너 생성시 사전에 설정할 수 있다. DB나 특정 어플리케이션들은 환경변수가 필수이며, 해당 환경변수 관련해서는 Docker hub의 description을 참고해야 한다.

--env=[환경변수], -e

환경변수 설정. -e -e -e 이런식으로 여러개 나열해서 명시할 수있음.

--env-file=[파일명]

환경변수를 파일로부터 설정(양이 많을 때)

--read-only=[true | false]

컨테이너의 파일 시스템을 읽기 전용으로 만듬

--workdir=[경로], -w

컨테이너의 작업 디렉토리 (시작디렉토리) 지정. 디렉토리는 자동으로 만들어진다.

--user=[사용자명], -u

사용자명 또는 UID를 지정한다.

 

예시 : 환경변수 설정

docker container run -it -e foo=bar centos /bin/bash

컨테이너 들어간 후, set 명령을 치면 설정된 환경변수들을 확인할 수 있다.

 

예시 : 환경변수 파일로 여러개 일괄 등록하기

# cat env_list
hoge=fuga
foo=bar

docker container run -it --env-file=/test/env_list centos /bin/bash

 

예시 : 컨테이너의 작업 디렉토리를 지정하기

docker container run -it -w=/tensorflow centos /bin/bash

 

 

 

자원설정 옵션

다음 포스팅에서 상세하게 확인할 수 있다.

2020/05/15 - [Docker Basic] - [Docker Basic] 15. Docker Container 자원 제한

 

[Docker Basic] 15. Docker Container 자원 제한

도커 컨테이너에서는 여러가지 자원을 할당할 수 있는데, 할당하지 않으면 해당 컨테이너는 마음대로 호스트의 자원을 사용한다. (CPU, MEMORY, swap 등) 따라서 어플리케이션에 따라 사용하는 자원�

watch-n-learn.tistory.com

 

 

 

# 추가 개념 이해 : 도커 컨테이너가 꺼질 때도 있고 안꺼질 때도 있는데..??

도커 컨테이너를 단순히 나갈려고 했는데 컨테이너가 내려가는 경우가 많다. Production 장비에서는 매우 위험한 일이므로 docker run의 개념과 컨테이너 내부에서 exit 명령과 ctrl+p+q 를 정확히 이해해야 한다. 테스트에는 "운영체제" 컨테이너와 "프로그램" 컨테이너 2가지에 따라 실행 및 종료 옵션을 여러가지 변경하여 테스트를 해 보았다. 그냥 아무생각 없이 도커에서 아래 내용을 쭉 쳐보면서 설명을 읽어보면 컨테이너가 어떻게 작동하는지 어느정도 감을 잡을 수 있을 것이다.

 

* 운영체제 컨테이너

 

docker run ubuntu 

프롬프트 떨어짐. 컨테이너 종료됨
docker ps -a로 확인하면, COMMAND 부분이 "/bin/bash"라고 되어있음.
포그라운드에서 bash 쉘을 실행한 후, 추가로 할 것이 없으므로 종료된다.

 

docker run ubuntu /bin/bash 

 

프롬프트 떨어짐.  컨테이너 종료됨. 위와 동일하다.
docker ps -a로 확인하면, COMMAND 부분이 "/bin/bash"라고 되어있음.

포그라운드에서 bash 쉘을 실행한 후, 추가로 할 것이 없으므로 종료된다.


docker run -it ubuntu

컨테이너 프롬프트로 들어가짐.  exit 로 나가면 컨테이너 종료됨. ctrl+p+q 로 나가면 계속 살아있음
docker attach 컨테이너명 으로 들어간 후 exit 쳐서 나가면, 컨테이너는 종료된다.

attach는 단순히 컨테이너에 붙은 것이고, 현재 컨테이너상태에 대하여 exit를 했기 때문.

컨테이너의 표준 입력 옵션이 들어있으므로 컨테이너에 진입된 상태가 유지된다.


docker run -it ubuntu /bin/bash
컨테이너 프롬프트로 들어가짐.  exit 로 나가면 컨테이너 종료됨.  ctrl+p+q 로 나가면 계속 살아있음. 위와 동일하다.
docker attach 컨테이너명 으로 들어간 후 exit 쳐서 나가면, 컨테이너는 종료된다.

attach는 단순히 컨테이너에 붙은거고, 현재 컨테이너상태에 대하여 exit를 했기 때문.

컨테이너의 표준 입력 옵션이 들어있으므로 컨테이너에 진입된 상태가 유지된다.

 

docker run -d ubuntu
프롬프트 떨어짐. 종료됨
docker ps -a로 확인하면, COMMAND 부분이 "/bin/bash"라고 되어있음.

백그라운드에서 bash 쉘을 실행한 후, 추가로 할 것이 없으므로 종료된다.


docker run -d ubuntu /bin/bash
프롬프트 떨어짐. 종료됨
docker ps -a로 확인하면, COMMAND 부분이 "/bin/bash"라고 되어있음.
백그라운드에서 bash 쉘을 실행한 후, 추가로 할 것이 없으므로 종료된다


docker run -it -d ubuntu
프롬프트 떨어짐. 종료되지 않음. 백그라운드에서 bash 쉘이 실행되고 표준 입력이 실행된 상태이기 때문.
docker ps -a로 확인하면, COMMAND 부분이 "/bin/bash"라고 되어있음.
docker exec -it ubuntu /bin/bash로 들어간 후 exit 쳐서 나가면, 컨테이너는 종료되지 않는다. exec로 실행한 /bin/bash가 종료되었을뿐.
docker attach 컨테이너명 으로 들어간 후 exit 쳐서 나가면, 컨테이너는 종료된다. attach는 단순히 컨테이너에 붙은거고, 현재 컨테이너상태에 대하여 exit를 했기 때문.

 

docker run -it -d ubuntu /bin/bash
프롬프트 떨어짐. 종료되지 않음. 백그라운드에서 bash 쉘이 실행되고 표준 입력이 실행된 상태이기 때문.
docker ps -a로 확인하면, COMMAND 부분이 "/bin/bash"라고 되어있음.
docker exec -it ubuntu /bin/bash로 들어간 후 exit 쳐서 나가면, 컨테이너는 종료되지 않는다. exec로 실행한 /bin/bash가 종료되었을뿐.
docker attach 컨테이너명 으로 들어간 후 exit 쳐서 나가면, 컨테이너는 종료된다. attach는 단순히 컨테이너에 붙은거고, 현재 컨테이너상태에 대하여 exit를 했기 때문.

 


* 소프트웨어 컨테이너


docker run httpd:latest
이렇게 하면, 로그만 뜨고 대기함. 프롬프트도 안뜸. ctrl+c 로 나가면, 컨테이너 종료됨, docker ps -a로 확인하면, COMMAND 부분이 "http-foreground"라고 되어있음.
crtl+c 나가기 전에, 창을 하나 더 띄워서 docker ps 로 보면 살아있다.

즉 OS에 httpd를 실행시켜놓은 상태로 run 되었고, 계속 실행중이므로 프롬프트 없이 대기하는 것임.


docker run httpd:latest /bin/bash
이렇게 하면, 그냥 끝남. 프롬프트 떨어짐. /bin/bash라는 배쉬 쉘을 실행한 후, 할게 없으니 종료된다. docker ps -a로 확인하면, COMMAND 부분이 "/bin/bash"라고 되어있음.

실제로 이것은 httpd가 실행되어있는 컨테이너의 OS에서 /bin/bash를 실행한 것이다. /bin/bash를 실행하고 할 게 없으므로 종료되는 것.

 

docker run -it httpd:latest
이렇게 하면, 로그 뜨고 컨테이너 프롬프트가 뜬다. httpd가 올라가 있는 컨테이너 OS를 포그라운드로 실행했으므로.

ctrl+c로 나가면 컨테이너는 종료된다. 즉, httpd가 종료되며 컨테이너도 종료되는 것.
docker ps -a로 확인하면, COMMAND 부분이 "http-foreground"라고 되어있음.

docker run -it httpd:latest /bin/bash
이렇게 하면, 컨테이너 프롬프트가 뜬다. httpd가 올라가 있는 컨테이너 OS에 /bin/bash를 포그라운드로 실행했으므로.
exit로 나가면 컨테이너가 종료된다. 즉 컨테이너 실행시 명시한 /bin/bash가 끝났기 때문에 컨테이너 자체가 종료되는 것.
crtl+c 나가기 전에, 창을 하나 더 띄워서 docker ps 로 보면 살아있다.
이상태에서, docker exec -it 이름 /bin/bash 라고 하면 들어가짐. 들어간 후 exit 하면? 컨테이너는 살아있다. 이유는? exec로 실행한 /bin/bash 만 종료했기 때문. 최초 실행한 /bin/bash는 실행된 상태에서 아직 유지중.
docker attach 컨테이너명 으로 들어간 후 exit 쳐서 나가면, 컨테이너는 종료된다. attach는 단순히 컨테이너에 붙은거고, 현재 컨테이너상태에 대하여 exit를 했기 때문.

docker run -d httpd:latest
이렇게 하면, 그냥 프롬프트 떨어지고, 컨테이너는 계속 살아있다.
이상태에서, docker exec -it 이름 /bin/bash 라고 하면 들어가짐. 들어간 후 exit 하면? 컨테이너는 살아있다. 이유는? exec로 실행한 /bin/bash 만 종료했기 때문.
docker attach 컨테이너명 으로 들어간 후 exit 쳐서 나가면, 컨테이너는 종료된다. attach는 단순히 컨테이너에 붙은거고, 현재 컨테이너상태, 즉 httpd을 실행한 것에 대하여 exit를 했기 때문.

docker run -d httpd:latest /bin/bash
이렇게 하면 그냥 프롬프트 떨어지고, 컨테이너는 종료된다.
/bin/bash를 백그라운드로 실행시키고 할 게 없으니 종료된 것임.

docker run -it -d httpd:latest
이렇게 하면, 프롬프트 떨어지고 컨테이너는 계속 살아있다.
이상태에서, docker exec -it 이름 /bin/bash 라고 하면 들어가짐.

들어간 후 exit 하면? 컨테이너는 살아있다. 이유는? exec로 실행한 /bin/bash 만 종료했기 때문. 그냥 -d로 한 것과 동일하다.
docker attach 컨테이너명 으로 들어가면 바로 종료된다. -it 옵션이 인터렉티브 모드이고, 인터렉티브 상태를 attach 했는데 그 후 할 게 없으므로 종료됨. (조심해야 할 듯)

attach는 단순히 컨테이너에 붙은거고, 현재 컨테이너상태에 대하여 exit를 했기 때문.

docker run -it -d httpd:latest /bin/bash
이렇게 하면, 프롬프트 떨어지고 컨테이너는 계속 살아있다. 
이상태에서, docker exec -it 이름 /bin/bash 라고 하면 들어가짐. 위와 다른점은

들어간 후 exit 하면? 컨테이너는 살아있다. 이유는? exec로 실행한 /bin/bash 만 종료했기 때문.  그냥 -d로 한 것과 동일하다.
docker attach 컨테이너명 으로 들어간 후 exit 쳐서 나가면, 컨테이너는 종료된다. attach는 단순히 컨테이너에 붙은거고, 현재 컨테이너상태에 대하여 exit를 했기 때문.

 


결론
- 도커 컨테이너 실행시 어떤 명령어로, 어떤 옵션으로  실행시켰느냐에 따라 도커 생성의 정체성이 달라지므로, 그 정체성에 따라 exit를 쳤을때 컨테이너가 종료될수도, 종료되지 않을수도 있음.
- 도커 컨테이너가 종료되지 않을려면, 도커 컨테이너 실행시 시작한 프로그램을 종료하지 않도록 해야 한다.
- attach 명령어는 stdout, stderr을 가져오는 것이다. ssh처럼 연결되는 것이 아니다. 
-  모르면 exit로 나가지 말고, ctrl+p+q 하는게 가장 좋다.

+ Recent posts