# Docker 기본 명령어

img

앞에서 도커의 run 명령어를 이용하여 여러개의 컨테이너를 실행했다. 이제 컨테이너의 상태를 살펴보고 어떤 이미지가 설치되어 있는지 확인하는 명령어를 알아보자.

# 컨테이너 목록 확인하기 (ps)

컨테이너 목록을 확인하는 명령어는 다음과 같다.

docker ps \[OPTIONS\]

일단 기본옵션과-a, --all옵션만 살펴보자.

docker ps

output:

CONTAINER ID        IMAGE                           COMMAND                  CREATED              STATUS              PORTS                                                    NAMES
6a1d027b604f        teamlab/pydata-tensorflow:0.1   "/opt/start"             About a minute ago   Up About a minute   0.0.0.0:6006->6006/tcp, 22/tcp, 0.0.0.0:8888->8888/tcp   desperate_keller
52a516f87ceb        wordpress                       "docker-entrypoint.sh"   8 minutes ago        Up 8 minutes        0.0.0.0:8080->80/tcp                                     happy_curran
2e2c569115b9        mysql:5.7                       "docker-entrypoint.sh"   9 minutes ago        Up 9 minutes        0.0.0.0:3306->3306/tcp                                   mysql
56341072b515        redis                           "docker-entrypoint.sh"   16 minutes ago       Up 9 minutes        0.0.0.0:1234->6379/tcp                                   furious_tesla

ps명령어는 실행중인 컨테이너 목록을 보여준다. detached mode로 실행중인 컨테이너들이 보인다.

어떤 이미지를 기반으로 만들었는지 어떤 포트와 연결이 되어있는지 등 간단한 내용을 보여준다.

이번에는-a옵션을 추가로 실행해보자.

docker ps -a

output:

CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS                      PORTS                                                    NAMES
6a1d027b604f        teamlab/pydata-tensorflow:0.1   "/opt/start"             2 minutes ago       Up 2 minutes                0.0.0.0:6006->6006/tcp, 22/tcp, 0.0.0.0:8888->8888/tcp   desperate_keller
52a516f87ceb        wordpress                       "docker-entrypoint.sh"   9 minutes ago       Up 9 minutes                0.0.0.0:8080->80/tcp                                     happy_curran
2e2c569115b9        mysql:5.7                       "docker-entrypoint.sh"   10 minutes ago      Up 10 minutes               0.0.0.0:3306->3306/tcp                                   mysql
56341072b515        redis                           "docker-entrypoint.sh"   18 minutes ago      Up 10 minutes               0.0.0.0:1234->6379/tcp                                   furious_tesla
e1a00c5934a7        ubuntu:16.04                    "/bin/bash"              32 minutes ago      Exited (0) 32 minutes ago                                                            berserk_visvesvaraya

맨 처음 실행했다가 종료된 컨테이너(Exited (0))가 추가로 보인다. 컨테이너는 종료되어도 삭제되지 않고 남아있다!

종료된 건 다시 시작할 수 있고 컨테이너의 읽기/쓰기 레이어는 그대로 존재한다. 명시적으로 삭제를 하면 깔끔하게 컨테이너가 제거된다. ​

# 컨테이너 중지하기 (stop)

​ 실행중인 컨테이너를 중지하는 명령어는 다음과 같다.

docker stop \[OPTIONS\] CONTAINER \[CONTAINER...\]
​```

옵션은 특별한게 없고 실행중인 컨테이너를 하나 또는 여러개 (띄어쓰기로 구분) 중지할 수 있다.  
​
앞에서 실행한 tensorflow 컨테이너는 더 이상 필요가 없으니 중지해 보겠다. 

중지하려면 컨테이너의 ID 또는 이름을 입력하면 된다. `tensorflow` 컨테이너의 ID를 ps명령을 통해 확인하고 중지해보자.
​
```shell script
docker ps # get container ID
docker stop ${TENSORFLOW_CONTAINER_ID}
docker ps -a # show all containers

도커 ID의 전체 길이는 64자리 입니다. 하지만 명령어의 인자로 전달할 때는 전부 입력하지 않아도 됩니다. 예를 들어 ID가abcdefgh...라면abcd만 입력해도 됩니다. 앞부분이 겹치지 않는다면 1-2자만 입력해도 됩니다. ​ 잠시 기다리면 tensorflow 컨테이너가 종료된다. ps -a명령어를 입력하여 종료되었는지 확인한다.

# 컨테이너 제거하기 (rm)

​ 종료된 컨테이너를 완전히 제거하는 명령어는 다음과 같다.

docker rm \[OPTIONS\] CONTAINER \[CONTAINER...\]
​```

종료 명령어도 옵션은 특별한게 없다. 종료된 컨테이너를 하나 또는 여러개 삭제할 수 있다. 종료된 ubuntu 컨테이너와 tensorflow 컨테이너를 삭제해보자.
​
```shell script
docker ps -a # get container ID
docker rm ${UBUNTU_CONTAINER_ID} ${TENSORFLOW_CONTAINER_ID}
docker ps -a # check exist

컨테이너가 말끔히 삭제된다. 호스트 OS는 아무런 흔적도 남아있지 않고 컨테이너만 격리된 상태로 실행되었다가 삭제되었다. 시스템이 꼬일 걱정이 없다! ​

중지된 컨테이너를 일일이 삭제 하는 건 귀찮은 일입니다.docker rm -v $(docker ps -a -q -f status=exited)명령어를 입력하면 중지된 컨테이너 ID를 가져와서 한번에 삭제합니다. ​

# 이미지 목록 확인하기 (images)

​ 도커가 다운로드한 이미지 목록을 보는 명령어는 다음과 같다.

docker images \[OPTIONS\] \[REPOSITORY\[:TAG\]\]
​```

간단하게 도커 이미지 목록을 확인해보자.
​
```shell script
docker images

output:

REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
wordpress                   latest              b1fe82b15de9        43 hours ago        400.2 MB
redis                       latest              45c3ea2cecac        44 hours ago        182.9 MB
mysql                       5.7                 f3694c67abdb        46 hours ago        400.1 MB
ubuntu                      16.04               104bec311bcd        4 weeks ago         129 MB
teamlab/pydata-tensorflow   0.1                 7bdf5d7e0191        6 months ago        3.081 GB
​

이미지 주소와 태그, ID, 생성시점, 용량을 확인할 수 있다. 이미지가 너무 많이 쌓이면 용량을 차지하기 때문에 사용하지 않는 이미지는 지우는 것이 좋겠다. ​

# 이미지 다운로드하기 (pull)

​ 이미지를 다운로드하는 명령어는 다음과 같다. ​

docker pull \[OPTIONS\] NAME\[:TAG|@DIGEST\]
​```

ubuntu:14.04를 다운받아보자.
​
```shell script
docker pull ubuntu:14.04​

run 명령어를 입력하면 이미지가 없을 때 자동으로 다운받으니 pull명령어를 언제 쓰는지 궁금할 수 있는데 pull은 최신버전으로 다시 다운받는다.

같은 태그지만 이미지가 업데이트 된 경우는 pull명령어를 통해 새로 다운받을 수 있다. ​

# 이미지 삭제하기 (rmi)

​ 이미지를 삭제하는 방법은 다음과 같다.

docker rmi \[OPTIONS\] IMAGE \[IMAGE...\]
​```

images명령어를 통해 얻은 이미지 목록에서 이미지 ID를 입력하면 삭제가 된다. 

단, 컨테이너가 실행중인 이미지는 삭제되지 않는다. 컨테이너는 이미지들의 레이어를 기반으로 실행중이므로 당연히 삭제할 수 없다.
​
tensorflow는 더 이상 사용하지 않으니 이미지를 제거해보겠다.
​
```shell script
docker images # get image ID
docker rmi ${TENSORFLOW_IMAGE_ID}

output:

Untagged: teamlab/pydata-tensorflow:0.1
Untagged: teamlab/pydata-tensorflow@sha256:cb5e036afc0aa647a6fe1f384475275aeed946c751de5209d84282c986589b7f
Deleted: sha256:7bdf5d7e0191a6133a385ac69ec6a07be46b08cf5b5e6b826a89b9b47aadabe5
Deleted: sha256:9d72165f240630813a39e2f802a75f45caa2bc230881fa73c2f620c4b04686b5
Deleted: sha256:5c90ba76fff96b155b8a9446f2fb42d2ae04566832f3929df41dc52c0ae462ae
Deleted: sha256:1e23db6b02673d34c54fe87ec958ae8f2e310ca4aa911c7f8488b6c7988bfba0
Deleted: sha256:759641367a6788b55361f9eeedcbc356f8e464ef794a883b5621fba6e23c6b18
Deleted: sha256:b5d017cd48c0d8461230b5ab0aed68e27a4018996344470db3c4b5adba10b49f
Deleted: sha256:470cdb158a12a416ffebde8d299fdbde28d56da062c701bf7a51d6484f777e97
Deleted: sha256:d136c3aea28597fadb667a084a6e5701e287fd36f03cc9555b0e5bca2e674f9b
Deleted: sha256:e62e6cce767baec3711dc1ec8cfcd76f68b88a6ca9ffcd2f3d22345048a0f8d7
Deleted: sha256:8e0761516c1c1ad792c9e67d1541d574905f067cb3b67e19a3af58ca7389eee9
Deleted: sha256:ad45f6539a6ce95216c9990d26b4b2e44c0b50637c1f0949b6965610b023fd97
Deleted: sha256:ebe200261801abef54e60699c098def3a4bd39a7b4833f164b99e23a88e8a98a
Deleted: sha256:698c310f0ec8a1f607a59f15a6affa7d9d21e21d9eaf6eb65b6ab6f33fcb62b4
Deleted: sha256:e5da0b4fd6d0143d7953e47a244a9be16919d1f4018e128e82fba6df967e790e
Deleted: sha256:7d8ffbfe2c1a55581e08b81f34506a746022e5beeb85f5848154b0b7d41208cf
Deleted: sha256:854cd556e616f5e5b21cd69f1e7c0d225c9b28eb5cf653aa4aa0937930298d72
Deleted: sha256:10e6f47febf1912a4d7a08b7652e360905a6ba8b76f188fd167c8d6afa09951a
Deleted: sha256:737ee41ad49072c9ba8301a17751e16d69c1045df74ac77f4ae05f849b08faec
Deleted: sha256:62b01cf4b1440085b0b9311372eb8acb509581faf655b2837a2e234c12fdfd24
Deleted: sha256:7dcdbe5fc9a2290d596e3bab8052c3141a69a451a29a98bd12678a7139891094
Deleted: sha256:8a9f069492b445dc889f9639572dc289f7c3fc1ac4d597a7468614fa2c624091
Deleted: sha256:34a63dcc0c5574597918a8e9df80e364f9fec88c0f4e25a0e5187acd241773ad
Deleted: sha256:af6fa43db2e379d3f0f3f36d61a0ece782133314c678d7223872eb7158f102ba
Deleted: sha256:efbafc7aa3a87241c10bf0c495672cf4a7b0cc2d23db06120ae1e13528316f82
Deleted: sha256:ea0c616be3659f71afce45eff2e28e51e04b25f1ae58b306521e6877f3adf2df
Deleted: sha256:f2dccb8902ea3d85aa9a954af894f59100fc00fa78c09b213c76dcf2727e3c3e
Deleted: sha256:3fe0adbd3614d696ded87bcb47aed81f49b113770a3778e276cd88abe9010b9f
Deleted: sha256:b88d260c0bcff3b4434a39ba33f58a2f9807400d664185057edd393133630242
Deleted: sha256:4de08f41d77237b2dbc0660036fe8352fdbacf6e079623d318003ed7e833a40a
Deleted: sha256:f32c8f02713c719181c2bf32be13dbd333932411d5fc3e0b6cfb780da8bb8124
Deleted: sha256:985d69571ed5d6d7e69bf58232fd8f30f8cd4ac77f41122a80fdab56347ec22d
Deleted: sha256:8509bc9969877f784fa6e704098cbcf77d694596644f389c5a2fefe5267878ab
Deleted: sha256:0ad5b9ed74fe2eee856b368d426cdd9335a6a6ecec0c4c705b5153c219a82692
Deleted: sha256:b159c847c5b9b899c23eba59395a4d7b7b275a8c686191ed6c4ef21ceadad8a2
Deleted: sha256:89e9f76552fd1a8d249c1e133e4c8964fe1f9104bb708db1e0ca6f6171ee4c22
Deleted: sha256:6d31e1827ca8f5037077314b2403eabd82590f9eae8baf956a2c2a819db68d4e
Deleted: sha256:7f4734de8e3dd402f10030f06bcb8781129b1eb6a25c58811a76d015f2a0982f

이미지가 삭제되었다. 이미지는 여러개의 레이어로 구성되어 있기 때문에 모든 레이어가 삭제된 것을 알 수 있다. ​

# 컨테이너 둘러보기

​ 도커에 대한 아주 기본적인 명령어를 살펴보았다.

사실 저 명령어들과 이번에 살펴볼 log,exec명령어를 익히면 도커에서 사용하는 명령어는 거의 다 익혔다고 할 수 있다.

다른 명령어는 필요에 따라 하나하나 살펴보면 된다! ​

# 컨테이너 로그 보기 (logs)

​ 컨테이너가 정상적으로 동작하는지 확인하는 좋은 방법은 로그를 확인하는 것이다. 로그를 확인하는 방법은 다음과 같다. ​

docker logs \[OPTIONS\] CONTAINER
​```

기본 옵션과,\-f, --tail옵션을 살펴본다.
​
기존에 생성해 놓은 워드프레스 컨테이너 로그를 확인해 보자.
​
```shell script
docker ps
docker logs ${WORDPRESS_CONTAINER_ID}

output:

WordPress not found in /var/www/html - copying now...
Complete! WordPress has been successfully copied to /var/www/html
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
[Thu Jan 19 16:10:16.507735 2017] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.10 (Debian) PHP/5.6.29 configured -- resuming normal operations
[Thu Jan 19 16:10:16.507776 2017] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
172.17.0.1 - - [19/Jan/2017:16:11:54 +0000] "GET / HTTP/1.1" 302 379 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:11:54 +0000] "GET /wp-admin/install.php HTTP/1.1" 200 2513 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/css/buttons.min.css?ver=4.7.1 HTTP/1.1" 200 1698 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/js/zxcvbn-async.min.js?ver=1.0 HTTP/1.1" 200 582 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-admin/css/install.min.css?ver=4.7.1 HTTP/1.1" 200 2329 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/js/jquery/jquery-migrate.min.js?ver=1.4.1 HTTP/1.1" 200 4366 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/js/jquery/jquery.js?ver=1.12.4 HTTP/1.1" 200 34120 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-admin/js/password-strength-meter.min.js?ver=4.7.1 HTTP/1.1" 200 825 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/js/wp-util.min.js?ver=4.7.1 HTTP/1.1" 200 924 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-admin/js/user-profile.min.js?ver=4.7.1 HTTP/1.1" 200 2590 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/js/underscore.min.js?ver=1.8.3 HTTP/1.1" 200 6173 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/css/dashicons.min.css?ver=4.7.1 HTTP/1.1" 200 28951 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-admin/images/wordpress-logo.svg?ver=20131107 HTTP/1.1" 200 1810 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:02 +0000] "GET /wp-includes/js/zxcvbn.min.js HTTP/1.1" 200 330747 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:02 +0000] "GET /favicon.ico HTTP/1.1" 200 229 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
::1 - - [19/Jan/2017:16:12:08 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.10 (Debian) PHP/5.6.29 (internal dummy connection)"
::1 - - [19/Jan/2017:16:12:09 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.10 (Debian) PHP/5.6.29 (internal dummy connection)"
::1 - - [19/Jan/2017:16:12:10 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.10 (Debian) PHP/5.6.29 (internal dummy connection)"

컨테이너에서 실행한 로그가 보인다. 아무 옵션을 주지 않았을 때는 전체 로그를 전부 다 출력한다. 너무 많으니 --tail옵션으로 마지막 10줄만 출력해보자.

docker logs --tail 10 ${WORDPRESS_CONTAINER_ID}

output:

172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/js/wp-util.min.js?ver=4.7.1 HTTP/1.1" 200 924 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-admin/js/user-profile.min.js?ver=4.7.1 HTTP/1.1" 200 2590 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/js/underscore.min.js?ver=1.8.3 HTTP/1.1" 200 6173 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-includes/css/dashicons.min.css?ver=4.7.1 HTTP/1.1" 200 28951 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:01 +0000] "GET /wp-admin/images/wordpress-logo.svg?ver=20131107 HTTP/1.1" 200 1810 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:02 +0000] "GET /wp-includes/js/zxcvbn.min.js HTTP/1.1" 200 330747 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
172.17.0.1 - - [19/Jan/2017:16:12:02 +0000] "GET /favicon.ico HTTP/1.1" 200 229 "http://localhost:8080/wp-admin/install.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12"
::1 - - [19/Jan/2017:16:12:08 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.10 (Debian) PHP/5.6.29 (internal dummy connection)"
::1 - - [19/Jan/2017:16:12:09 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.10 (Debian) PHP/5.6.29 (internal dummy connection)"
::1 - - [19/Jan/2017:16:12:10 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.10 (Debian) PHP/5.6.29 (internal dummy connection)"

마지막 10줄만 보니 좀 나아 보인다. ​ 실시간으로 로그가 생성되는 것을 확인해보려면 -f 옵션으로 실행하면 된다!

docker logs -f

로그를 켜 놓은 상태에서 워드프레스 페이지를 새로고침하면 브라우저 접속 로그가 실시간으로 보일 것이다. 가장 흔하게 사용하는 옵션이고 로그 보기를 중지하려면 ctrl+c 를 입력하면 된다.
로그에 대해 좀 더 자세히

프로그램마다 로그 파일은 제각각 생길텐데 어떻게 저 로그가 나올까 라는 의문이 생긴다.

도커는 로그파일을 자동으로 알아채는게 아니라표준 스트림( (opens new window)Standard streams) 중 stdout,stderr를 수집한다. 따라서 컨테이너에서 실행되는 프로그램의 로그 설정을 파일이 아닌 표준출력으로 바꾸어야 한다. 단지 출력 방식만 바꾸는 것으로 모든 컨테이너는 로그에 대해 같은 방식으로 관리할 수 있게 된다! ​ 또 하나 중요한 점은 컨테이너의 로그파일은 json 방식으로 어딘가에 저장이 된다. 로그가 많으면 은근히 파일이 차지하는 용량이 커지므로 주의해야한다. 도커는 다양한 플러그인을 지원하여 json이 아닌 특정 로그 서비스에 스트림을 전달할 수 있다. 어느 정도 앱의 규모가 커지면 기본적인 방식 대신 로그 서비스를 이용하는 걸 고려해야한다. ​

# 컨테이너 명령어 실행하기 (exec)

​ 컨테이너를 관리하다 보면 실행중인 컨테이너에 들어가보거나 컨테이너의 파일을 실행하고 싶을 때가 있다.

컨테이너에 SSH를 설치하면 되지 않을까? 라고 생각할 수 있지만 SSH는 권장하지 않는다.

예전에는nsenter (opens new window)라는 프로그램을 이용하였는데 docker에exec라는 명령어로 흡수되었다. ​

컨테이너 명령어를 실행하는 방법은 다음과 같다. ​

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
```​


run명령어와 유사해 보인다. 차이는 run은 새로 컨테이너를 만들어서 실행하고 exec는 실행중인 컨테이너에 명령어를 내리는 정도이다.
​
일단, 가볍게 실행중인 `MySQL` 컨테이너에 접속해보자.
​
```shell script
docker exec -it mysql /bin/bash
​
# MySQL test
$ mysql -uroot
​
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wp                 |
+--------------------+
5 rows in set (0.00 sec)
​
mysql> quit
exit

키보드 입력이 필요하니 run 명령어와 마찬가지로 -it옵션을 주었고 bash 쉘로 접속하여 마치 가상머신에 들어온 것 같은 느낌이 든다. 접속한 이후에는 어떤 작업도 할 수 있고 컨테이너를 마음껏 건드릴 수 있다. ​

쉘로 완전한 권한을 얻는 방법말고 바로 mysql명령어를 실행 할 수도 있다. ​

docker exec -it mysql mysql -uroot# MySQL test
$ mysql -uroot
​
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wp                 |
+--------------------+
5 rows in set (0.00 sec)
​
mysql> quit

이제, 호스트 OS에 mysql을 설치하지 않아도 mysql 클라이언트를 사용할 수 있다.

굳이 복잡한 작업이 필요 없는 경우는 -it옵션 없이 단순하게 명령을 실행하고 종료할 수도 있다. ​

# 컨테이너 업데이트

이제 지금까지 배운 모든걸 정리해서 컨테이너를 새로운 버전으로 업데이트 하는 과정을 살펴보자. ​ img ​ 도커에서 컨테이너를 업데이트 하려면 새 버전의 이미지를 다운(pull)받고 기존 컨테이너를 삭제(stop,rm) 한 후 새 이미지를 기반으로 새 컨테이너를 실행(run)하면 된다.

컨테이너를 삭제한다는 건 컨테이너에서 생성된 파일이 사라진다는 뜻이다. 데이터베이스라면 그동안 쌓였던 데이터가 모두 사라진다는 것이고 웹 어플리케이션이라면 그동안 사용자가 업로드한 이미지가 모두 사라진다는 것이다. ​

이런 상황을 방지하기 위해 컨테이너 삭제시 유지해야하는 데이터는 반드시 컨테이너 내부가 아닌 외부 스토리지에 저장해야한다.

가장 좋은 방법은AWS S3 (opens new window)같은 클라우드 서비스를 이용하는 것이고 그렇지 않으면 데이터 볼륨Data volumes을 컨테이너에 추가해서 사용해야 한다.

데이터 볼륨을 사용하면 해당 디렉토리는 컨테이너와 별도로 저장되고 컨테이너를 삭제해도 데이터가 지워지지 않는다. ​

데이터 볼륨을 사용하는 방법은 몇가지가 있는데 여기서는 호스트의 디렉토리를 마운트해서 사용하는 방법에 대해 알아본다.

run 명령어에서 소개한 옵션중에 -v 옵션을 드디어 사용해 보자. MySQL 이라면/var/lib/mysql 디렉토리에 모든 데이터베이스 정보가 담기므로 호스트의 특정 디렉토리를 연결해주면 된다.

# before
docker run -d -p 3306:3306 \
  -e MYSQL_ALLOW_EMPTY_PASSWORD=true \
  --name mysql \
  mysql:5.7
​
# after
docker run -d -p 3306:3306 \
  -e MYSQL_ALLOW_EMPTY_PASSWORD=true \
  --name mysql \
  -v /my/own/datadir:/var/lib/mysql \ # <- volume mount
  mysql:5.7

위 샘플은 호스트의 /my/own/datadir 디렉토리를 컨테이너의 /var/lib/mysql 디렉토리로 마운트 하였습니다. 이제 데이터베이스 파일은 호스트의 /my/own/datadir 디렉토리에 저장되고 컨테이너를 삭제해도 데이터는 사라지지 않습니다.

최신버전의 MySQL 이미지를 다운받고 다시 컨테이너를 실행할 때 동일한 디렉토리를 마운트 한다면 그대로 데이터를 사용할 수 있습니다. ​

# Docker Compose

​ 지금까지 도커를 커맨드라인에서 명령어로 작업했다. 지금은 간단한 작업만 했기 때문에 명령이 길지 않지만 컨테이너 조합이 많아지고 여러가지 설정이 추가되면 명령어가 금방 복잡해질 것이다. ​

도커는 복잡한 설정을 쉽게 관리하기 위해 YAML (opens new window)방식의 설정파일을 이용한 Docker Compose (opens new window)라는 툴을 제공한다. 깊게 파고들면 은근 기능이 많고 복잡한데 이번에는 아주 가볍게 다루고 지나가도록 하자. ​

# 설치하기

​ Docker for Mac 또는 Docker for Windows를 설치했다면 자동으로 설치된다. 리눅스의 경우 다음 명령어를 입력하여 설치한다. 그냥 설치파일 하나 다운받으면 된다!

curl -L "https://github.com/docker/compose/releases/download/1.9.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
# test
docker-compose version

# wordpress 만들기

​ 기존에 명령어로 만들었던 wordpress를 compose를 이용해 만들어 보자. ​ 먼저 빈 디렉토리를 하나 만들고docker-compose.yml파일을 만들어 설정을 입력한다.

version: '2'
​
services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: wordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress
​
   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     volumes:
       - wp_data:/var/www/html
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_PASSWORD: wordpress
volumes:
    db_data:
    wp_data:

몇몇 생소해보이는 설정이 눈에 보이지만, 일단 실행해 보자.

docker-compose up

아주 손쉽게 워드프레스가 만들어진다. 단지 명령어를 설정파일로 바꾼거에 불과하지만 가독성과 편리성은 훨씬 향상되었다. Docker Compose의 다른 기능과 생소한 설정내용은 나중에 더 공부하도록 하자. ​

# 정리

​ 여기까지 도커에 대해 기본적인 내용부터 컨테이너를 실행하고 살펴보는 방법까지 알아보았다. 이제 남이 만든 이미지를 사용하는 것이 아니라 직접 이미지를 만들고 컨테이너를 여러 서버로 배포하는 방법을 다음글에서 포스팅하겠다. ​

# Reference

​ ​ 초보를 위한 도커 안내서 - 설치하고 컨테이너 실행하기 (opens new window)

Last Updated: 6/18/2023, 2:13:15 PM