[Docker] Container run 이야기.

Docker 테스트 중 경험했던 container run 과 관련된 내용을 정리 해 본다.

Container 실행하고 접속하고 나오고…

우선 docker 가 설치되어 있다는 가정하에 ubuntu 이미지를 내려 받아본다.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker pull ubuntu
ubuntu:latest: The image you are pulling has been verified
511136ea3c5a: Pull complete
d497ad3926c8: Pull complete
ccb62158e970: Pull complete
e791be0477f2: Pull complete
3680052c0f5c: Pull complete
22093c35d77b: Pull complete
5506de2b643b: Pull complete

그리고 ubuntu 이미지가 잘 받아졌는지 확인도 해 보자.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker images
REPOSITORY   TAG      IMAGE ID       CREATED      VIRTUAL SIZE
ubuntu       latest   5506de2b643b   7 days ago   197.8 MB

자, 이제 이미지를 받았으니 run 을 통해서 container 를 실행해 보자. 우선 -i 와 -t 옵션으로 생성된 container 와 대화형으로 입출력을 실행할 수 있다.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker run -i -t ubuntu
root@ff73f9aaee31:/#

이렇게 container 를 실행하면 그 container 에 접속한것을 볼 수 있는데 기본적인container 실행 명령어는 /bin/bash 쉘이다. -i 와 -t 옵션으로 대화형 명령 콘솔로 접근이 가능했던것이다. 이제 이 상태에서 다른 터미널 하나(2번 터미널)를 띄워 현재의 container 리스트를 확인 해 본다.

ubuntu@ip-172–31–21–107-#2:~$ sudo docker ps -a
CONTAINER ID IMAGE         COMMAND      CREATED        STATUS
ff73f9aaee31 ubuntu:latest “/bin/bash”  2 minutes ago  Up 2 seconds

container ID 는 ‘ff73f9aaee31’ 이며 ubuntu:latest 이미지로 container 를 생성하였으며 실행되고 있는 명령어는 ‘/bin/bash’, STATUS 부분에 보면 ‘Up’ 으로 현재 container 가 띄워져있다는 것을 확인할 수 있다.

그럼 container 에 접속하고 있는 1번 터미널에서 exit로 빠져 나와보자. 그리고 다시 2번 터미널에서 container 상태를 확인해 본다.

CONTAINER ID IMAGE         COMMAND     CREATED       STATUS
ff73f9aaee31 ubuntu:latest “/bin/bash” 2 minutes ago Exited(0)..ago

container 상태가 ‘Up’ 에서 ‘Exit’ 로 변하였다. 이는 container 에서 bash 쉘로 접속중인 상태에서 exit 명령어로 쉘을 종료 하였기 때문에 container 도 쉘의 정상적인 종료 메시지(exit 0)를 받고 자연스럽게 종료상태로 변하게 된것이다.

그럼 어떻게 다시 접속 할 수 있을까? 종료된 container 에 다시 쉘로 접속하기 위해서는 start 명령어로 container 를 다시 시작한 후 attach 명령어로 접속을 한다.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker start ff73f9aaee31
ff73f9aaee31
ubuntu@ip-172–31–21–107-#1:~$ sudo docker ps -a
CONTAINER ID IMAGE         COMMAND     CREATED        STATUS
ff73f9aaee31 ubuntu:latest “/bin/bash” 2 minutes ago  Up 2 seconds
ubuntu@ip-172–31–21–107-#1:~$ sudo docker attach ff73f9aaee31
root@ff73f9aaee31:/#

그럼 이제 2번 터미널에서 container 를 한 번 지워보자.

ubuntu@ip-172–31–21–107-#2:~$ sudo docker rm ff73f9aaee31
Error response from daemon: You cannot remove a running container. Stop the container before attempting removal or use -f
2014/10/31 09:12:02 Error: failed to remove one or more containers

안된단다. 왜냐하면 container 가 이미 실행중이거든. 그래도 지우고 싶으면 -f 옵션으로 지우라고 안내하고 있다. 하지만 우아하게 종료 후 삭제하도록 하겠다.

ubuntu@ip-172–31–21–107-#2:~$ sudo docker stop ff73f9aaee31
ff73f9aaee31
ubuntu@ip-172–31–21–107-#2:~$ sudo docker rm ff73f9aaee31
ff73f9aaee31
ubuntu@ip-172–31–21–107-#2:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

여기까지 docker image 를 가지고 container 를 실행하고, 접속하고, 삭제까지 해 보았다.

Apache 를 설치하고 실행해보자

그럼 기본적으로 container 를 생성하고 실행도 하고 접속도 해보았으니 apache 를 설치해서 웹서버를 하나 실행해보자. 다시 container를 하나 생성해야겠다. 이번에는 웹서버를 실행할 것이기 때문에 -p 옵션으로 port 를 지정을 해야한다.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker run -i -t -p 80:80 ubuntu
root@d448434e362d:/#

‘d448434e362d’ ID의 새로운 container 가 실행되었다. 앞서 얘기한것 처럼 apache 웹서버를 실행할것이기 때문에 ‘-p <host port>:<container port>’ 을 이용하여 host:80 으로 들어오는 request 를 container:80 으로 매핑시켜도록 설정한다. 이제 apache 를 설치해 보자.

root@d448434e362d:/# apt-get update
...blahblahblah...
root@d448434e362d:/# apt-get install -y apache2
...blahblahblah...
root@d448434e362d:/# service apache2 start
 * Starting web server apache2
root@d448434e362d:/# ps -ef | grep apache2
root 886 1 0 09:08 ? 00:00:00 /usr/sbin/apache2 -k start
www-data 889 886 0 09:08 ? 00:00:00 /usr/sbin/apache2 -k start
www-data 890 886 0 09:08 ? 00:00:00 /usr/sbin/apache2 -k start

container 안에 apache2 프로세스가 떠있는것을 확인하였고 실제 브라우저에서 웹서버가 실행 되었는지 확인해 보자.

정상적으로 서버는 실행 되었고, 그럼 2번 터미널로 container 상태를 확인해 보자.

ubuntu@ip-172–31–21–107-#2:~$ sudo docker ps -a
CONTAINER ID   IMAGE                COMMAND          CREATED 
d448434e362d   ubuntu:latest        “/bin/bash”      6 minutes ago 
STATUS         PORTS                NAMES
Up 6 minutes   0.0.0.0:80->80/tcp   dreamy_poincare

container 는 실행중이며 PORTS 에서 80(host) -> 80(container) 로 매핑하고 있다는 것을 확인할 수 있다. 그럼 정상적으로 apache 를 실행하였으니 접속한 container 에서 exit 나가 보자.

root@d448434e362d:/# exit
exit
ubuntu@ip-172–31–21–107-#1:~$

근데 이게 왠걸. 브라우저에서 다시 한번 확인하였더니 페이지가 안뜨는 것이다. container 상태를 다시 확인 해보니

ubuntu@ip-172–31–21–107-#1:~$ sudo docker ps -a
CONTAINER ID   IMAGE           COMMAND       CREATED 
d448434e362d   ubuntu:latest   “/bin/bash”   6 minutes ago 
STATUS                         PORTS         NAMES
Exited (0) 5 seconds ago                     dreamy_poincare

STATUS 가 ‘Exited’ 로 container 가 종료 되었다. 어떻게 된 것일까? 예상했을 수 도 있었겠지만 이전처럼 container 안에서 exit 로 빠져나오는 순간 bash 쉘은 종료가 되어 container 도 같이 종료가 되는 것이었다. 그럼 container 가 종료 되지 않고 접속해있던 container 에서 빠져 나오는 방법은 없을까?

그러기 위해서는 container 에 접속한 상태에서 ctrl +p & ctrl + q 를 누르면 container 의 종료 없이 container 에서 빠져 나올 수 있는 것을 확인할 수 있다.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker attach d448434e362d
root@d448434e362d:/#
root@d448434e362d:/# (press ctrl + p + q)
ubuntu@ip-172–31–21–107:~$

그 후 다시 container 의 상태를 확인 해 보면 여전히 실행중인것을 확인 할 수 있다.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED 
d448434e362d ubuntu:latest “/bin/bash” 6 minutes ago
STATUS PORTS NAMES
Up 12 seconds 0.0.0.0:80->80/tcp dreamy_poincare

실행을 하였지만…

그럼 docker 를 실제 서비스 환경에서 운영한다고 했을때 매번 ctrl + p, q 를 통해 접속한 container 에서 빠져나와야 하는 것일까? 만일 누군가 실수로 exit 를 해버린다면? 아마 바로 container 가 종료 되고 서비스도 종료 되어 장애로 이어질 수 있을 것이다. 그럼 이를 해결할 수 있는 방법은 없을까?

앞서 맨 처음 우리가 container 를 ‘sudo docker run -i -t ubuntu’ 로 실행하였는데, 이때 이미지명(ubuntu) 뒤에 container 실행 시 수행할 명령어를 명시할 수 있는데 생략하게 되면 기본적으로 ‘/bin/bash’ 가 실행된다. 따라서 container 실행 시 명령어로 /bin/bash 가 아닌 apache 실행 명령어를 명시해주면 되지 않을 까?

우선 apache 가 설치되어 있는 container 를 commit 을 통하여 이미지를 저장해보자.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker ps -a
CONTAINER ID   IMAGE           COMMAND       CREATED 
d448434e362d   ubuntu:latest   “/bin/bash”   2 days ago
STATUS                         PORTS         NAMES 
Exited (0) 2 minutes ago                     dreamy_poincare
ubuntu@ip-172–31–21–107-#1:~$ sudo docker commit d448434e362d ubuntu:apache
d7e4c2f8af99601388d747d30205b8fd0d0eb8e7985ddafc060bcd7047e1ef4f
ubuntu@ip-172–31–21–107-#1:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu apache d7e4c2f8af99 8 seconds ago 232.6 MB
ubuntu latest 5506de2b643b 10 days ago 197.8 MB

이제 apache 가 설치되어 있는 ubuntu 이미지로 apache 실행명령을 통한 container 를 실행해보자.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker run -p 80:80 ubuntu:apache /bin/bash -c ‘service apache2 start’
 * Starting web server apache2
ubuntu@ip-172–31–21–107:~$

오, 시작되었다고 메시지가 떴다. 브라우저로 확인해보자. 하지만 apache 페이지는 볼 수 없을 것이다. 왜냐하면 container 는 종료 상태이다. apache 를 실행 하였지만 실행 과 동시에 시작 명령어의 수행이 끝났기 때문에 쉘도 종료가 되고 자연스럽게 container 도 같이 종료가 되었다. apache 를 계속 동작하게 하려면 apache 를 background 가 아닌 foreground 로 실행 시켜 명령어가 종료되지 않고 계속 실행되게끔 해준다.

ubuntu@ip-172–31–21–107-#1:~$ sudo docker run -p 80:80 ubuntu:apache /bin/bash -c ‘/usr/sbin/apache2ctl -D FOREGROUND’
(prompt...)

브라우저에서 확인하니 정상적으로 페이지를 확인할 수 있다. 근데 문제가 생겼다. apache 는 실행되었는데 apache 를 실행한 터미널에서 빠져나갈수가 없다. exit 나 ctrl + pq 도 소용없었다. 우선 2번 터미널로 가서 해당 container 를 종료 시키자.

ubuntu@ip-172–31–21–107-#2:~$ sudo docker stop 7d9f5e334295
7d9f5e334295

1번 터미널도 정상적으로 돌아 왔다. 이대로는 정상적으로 사용할 수 없을 것 같다. 따라서 docker run 자체도 foreground 가 아닌 ‘-d’ 옵션으로 background 모드 실행을 해야 한다.

ubuntu@ip-172–31–21–107:~$ sudo docker run -d -p 80:80 ubuntu:apache /bin/bash -c ‘/usr/sbin/apache2ctl -D FOREGROUND’
a47aef40a2f0aa23b370f9a5668c9787a6664692e0e7c9aa506d74b18549d331
ubuntu@ip-172–31–21–107:~$ sudo docker ps -a
CONTAINER ID  IMAGE          COMMAND              CREATED 
a47aef40a2f0  ubuntu:apache  “/bin/bash -c ‘/usr/ 4 seconds ago
STATUS        PORTS                               NAMES 
Up 3 seconds  0.0.0.0:80->80/tcp                  distracted_darwin

이제 docker 도 apache 도 정상적으로 실행하였으니 container 에 접속하여 로그를 한번 살펴보아야 겠다

ubuntu@ip-172–31–21–107:~$ sudo docker attach a47aef40a2f0
(prompt…)

이런… 또 망했다. 아무것도 할 수 가 없다. attach 로 접속하여 이전처럼 /bin/bash 쉘이 실행될거라 기대하였지만 이 container 는 실행할 때 apache forground 실행 명령어로 했기 때문에 foreground 명령어 수행 상태로 접속하게 된 것이다. 그럼 또 어떻게 해야하는 것인가.

docker 1.3 부터 ‘exec’ 명령어가 추가 되어 host 에서 container 로 명령어를 수행할 수 있게되었다. 따라서 attach 대신 exec 에 대화형 모드로 container 안으로 접속 할 수 있다. 이 때 ‘/bin/bash’ 꼭 명시해 준다.

ubuntu@ip-172–31–21–107:~$ sudo docker exec -i -t a47aef40a2f0 /bin/bash
root@a47aef40a2f0:/#

그리고 exec 로 접속한 container 에서는 exit 로 빠져나와도 현재 run 상태인 container에는 아무런 영향을 주지 않는다.

root@a47aef40a2f0:/# exit
exit
ubuntu@ip-172–31–21–107:~$

정리하면 docker container 를 이용하여 apache 를 지속적으로 실행하고 서비스 하고 싶다면 apache 를 foreground 로 docker container 를 background 로 실행하고 exec 를 통하여 container 에 접속하면 된다.

container 에 service 를 자동적으로 또는 지속적으로 실행하는 방식에는 위의 방식 이외에 upstart, systemd, supervisor 등의 방식도 있는데 이는 다음 기회에 다루어 보기로 하겠다.

참고자료

Advertisements

5개의 댓글

  1. apache foregrund 안하고 실행시키면 바로 종료되잖아요 이유알수있을가요? background 에서 apache 가 계속 실행중일텐데… docker 가 종료 시키는 이유를 모르겠어요..

    좋아하기


답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중