이 장에서는 Docker 명령의 기본적인 사용 방법과 주요 옵션을 살펴보기로 한다
# CentOS의 버전 7(태그명:7)을 다운로드
$ docker image pull centos:7
# CentOS의 모든 태그 이미지 취득
$ docker image pull -a centos
# Tensorflow 이미지 취득
$ docker image pull tensorflow/tensorflow
# 이미지 목록 표시
$ docker image ls
# 이미지 상세 정보 표시
$ docker image inspect centos:7
# OS 정보 취득
$ docker image inspect --format="{{.Os}}" centos:7
# image 정보 취득
$ docker image inspect --format="{{.ContainerConfig.Image}}" centos:7
# nginx라는 이름의 이미지에서 대해 사용자명이 titu고, 컨테이너명이 webserver이며, 태그에 버전 정보가 1.0인 태그를 붙일때
$ docker image tag nginx titu/webserver:1.0
# Docker Hub에 공개되어 있는 이미지 검색
$ docker search nginx
# 인기 있는 이미지 검색
$ docker search --filter=stars=100 nginx
# 이미지 삭제
$ docker image rm nginx
# 사용하지 않은 Docker 이미지 삭제
$ docker image prune
Docker 레포지토리에 업로드를 하려면 도커 로그인을 해야 한다.
# Docker Hub에 로그인
$ docker login
# 이미지 업로드
$ docker image push titu/webserver:1.0
# 이미지 삭제
$ docker image rm nginx
이미지가 만들어졌으면 컨테이너를 생성할 수 있다.
# centos라는 이름의 이미지를 바탕으로 test1이라는 이름의 컨테이너를 실행하고, 컨테이너 안에서 /bin/cal 명령을 실행
$ docker container run -it --name "test1" centos /bin/cal
# centos라는 이름의 이미지를 바탕으로 test1이라는 이름의 컨테이너를 실행하고, 컨테이너 안에서 /bin/bash 명령을 통해 컨테이너 안에서 쉘을 실행
$ docker container run -it --name "test2" centos /bin/bash
# 쉘 종료
$ exit
# centos라는 이름의 이미지를 바탕으로 하여 컨테이너를 생성하고, localhost에 대해 /bin/ping 명령을 실행
$ docker container run -d centos /bin/ping localhost
# 위 명령어를 실행했을때 표시된 컨테이너 ID를 통해 컨테이너 로그 확인
$ docker container logs -t (컨테이너 ID)
# 컨테이너를 항상 재시작 (명령 안에서 /bin/bash를 exit으로 종료해도 자동으로 컨테이너를 재시작한다)
$ docker container run -it --restart=always centos /bin/bash
[root@623e5f58f5be /]# exit
exit
$ docker container ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
623e5f58f5be centos "/bin/bash" 14 seconds ago Up 9 seconds romantic_boyd
컨테이너를 시작할 때 네트워크에 관한 설정을 할 수 있다.
# 컨테이너의 포트 번호와 호스트 OS의 포트 번호 매핑
# nginx라는 이름의 이미지를 바탕으로 컨테이너를 생성하고, 백그라운드에서 실행한다.
# 이때 호스트의 포트 번호 8080과 컨테이너의 포트 번호 80을 매핑시킨다.
# 이 명령을 실행하고 호스트의 8080 포트에 액세스하면 컨테이너에서 작동하고 있는 Nginx(80번 포트)의 서비스에 액세스할 수 있다.
$ docker container run -d -p 8080:80 nginx
# 컨테이너의 DNS 서버 지정
$ docker container run -d --dns 192.168.1.1 nginx
# 컨테이너의 MAC 주소 지정
$ docker container run -d --mac-address="92:d0:c6:0a:29:33" centos
9211133409f72e16d3c32b34fc913d3fed54183ac0dc21baf38df62d2709fc40
# 컨테이너 안의 네트워크 구성 확인
$ docker container inspect --format="{{.Config.MacAddress}}" 9211
92:d0:c6:0a:29:33
# 컨테이너의 안의 /etc/hosts에 호스트명과 IP 주소 정의
# 명령을 실행하고 컨테이너 안의 /etc/hosts를 확인하면 호스트명이 www.test.com과 node1.test.com(192.168.1.1)로 정의되어 있는 것을 알 수 있다.
$ docker container run -it --hostname www.test.com --add-host node1.test.com:192.168.1.1 centos
[root@www /]# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.1.1 node1.test.com
172.18.0.6 www.test.com www
# 외부 브리지 네트워크 드라이버를 사용하여 'webap-net'이라는 이름의 네트워크를 작성하고, 작성한 네트워크 상에서 컨테이너를 실행
$ docker network create -d bridge webap-net
$ docker container run --net=webap-net -it centos
CPU나 메모리와 같은 자원을 지정하여 컨테이너를 생성 및 실행할 수 있다.
# CPU 시간의 상대 비율과 메모리 사용량을 지정
$ docker container run --cpu-shares=512 --memory=lg centos
# 호스트 OS와 컨테이너 안의 디렉토리를 공유하고 싶을 때
# 호스트 OS의 /Users/asa/webap 폴더를 컨테이너의 /usr/share/nginx/html 디렉토리와 공유함
$ docker container run -v /Users/asa/webap:/usr/share/nginx/html nginx
컨테이너의 환경변수나 컨테이너 안의 작업 디렉토리 등을 지정하여 컨테이너를 생성/실행할 수 있다.
# 환경변수 설정
$ docker container run -it -e foo=bar centos /bin/bash
[root@0e838eb3ade6 /]# set
# 작업 디렉토리 설정
# 컨테이너의 /tensorflow를 작업 디렉토리로 설정함
$ docker container run -it -w=/tensorflow centos /bin/bash
[root@222a1fe7d233 tensorflow]# pwd
/tensorflow
Docker 상에서 작동하는 컨테이너의 가동 상태를 확인할 때는 docker container ls 명령을 사용한다.
# 컨테이너 목록 표시
$ docker container ls
# 컨테이너 목록의 필터링
# 이름에 test1이 포함된 컨테이너를 표시
$ docker container ls -a -f name=test1
# 컨테이너 목록의 필터링
# status에 종료 코드가 0인 컨테이너를 표시
$ docker container ls -a -f exited=0
# 컨테이너 목록의 출력 형식 지정
# 컨테이너 ID와 Status 출력
$ docker container ls -a --format "{{.Names}}:{{.Status}}"
# 컨테이너 목록을 표 형식으로 출력
$ docker container ls -a --format "table {{.Names}}\t{{.Status}}\t{{.Mounts}}"
도커 상에서 작동하는 컨테이너 가동 상태를 확인할 때
컨테이너에서 실행 중인 프로세스를 확인할 때
# 컨테이너 가동 확인
$ docker container stats webserver
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
5beeb2af6e2b webserver 0.00% 1.961MiB / 992.1MiB 0.20% 828B / 0B 0B / 8.19kB 3
# 컨테이너에서 실행 중인 프로세스 확인
$ docker container top webserver
UID PID PPID C STIME TTY TIME CMD
root 1534 1520 0 08:14 ? 00:00:00 nginx: master process nginx -g daemon off;
systemd+ 1593 1534 0 08:14 ? 00:00:00 nginx: worker process
# Docker container 시작
$ docker container start
# 컨테이너 Id가 5be~~인 컨테이너를 2초 후에 정지
$ docker container stop -t 2 5be
# 컨테이너명이 webserver인 컨테이너를 2초 후에 재시작
$ docker container restart -t 2 webserver
# webserver라는 이름의 컨테이너를 삭제
$ docker container rm webserver
$ docker container ls -a
# 정지 중인 컨테이너 삭제
$ docker container prune
$ docker container ls -a
# 컨테이너 중단
$ docker container pause webserver
$ docker container ls
# 중단 컨테이너의 재개
$ docker container unpause webserver
Docker 컨테이너끼리 통신을 할 때는 Docker 네트워크를 통해 수행한다.
Docker 네트워크 목록을 확인하기 위한 명령이다. Docker는 기본값으로 bridge, host, none, 이 세 개의 네트워크를 만든다.
# 네트워크 목록 표시
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
d06e9acfb760 bridge bridge local
a97b671cfa14 host host local
6cecdcf0fab7 none null local
# 브리지 네트워크의 네트워크 ID만을 목록으로 표시하고 싶을때
$ docker network ls -q --filter driver=bridge
d06e9acfb760
# 네트워크를 명시적으로 지정하지 않고 Docker 컨테이너를 시작하면 기본값인 'bridge' 네트워크로 Docker 컨테이너를 시작한다.
$ docker container run -itd --name=sample ubuntu:latest
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.NetworkID}}{{end}}' sample
d06e9acfb76094078126e49bc3980ecf6a5ab4b3d57663e1a92812c842b6f343
새로운 네트워크를 작성하기 위한 명령이다.
# 'web-network'라는 이름의 브리지 네트워크 작성
$ docker network create --driver=bridge web-network
413bddc36b6cb8ac1e72b4453e11ced7a8a4daa3cb7f8f7c9f9f8dda31d2ab7b
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
d06e9acfb760 bridge bridge local
a97b671cfa14 host host local
6cecdcf0fab7 none null local
413bddc36b6c web-network bridge local
Docker 컨테이너를 Docker 네트워크에 연결하고, 연결을 해제하기 위한 명령이다.
# 'sample'라는 이름의 컨테이너를 'web-network'라는 이름의 네트워크와 연결
$ docker network connect web-network sample
# 컨테이너에 속한 네트워크를 확인한다
$ docker container inspect sample
# 네트워크를 지정한 컨테이너 시작
# 베이스 이미지가 'nginx'이고 'webap'이라는 이름의 Docker 컨테이너를 'web-network' 네트워크에 만든다.
$ docker container run -itd --name=webap --net=web-network nginx
# 컨테이너에 속한 네트워크를 확인한다
$ docker container inspect webap
# 네트워크에 대한 연결 해제
$ docker network disconnect web-network webap
# 컨테이너에 속한 네트워크를 확인한다
$ docker container inspect webap
이름, ID, 드라이버, 서브넷, 게이트웨이, 컨테이너 등과 같은 네트워크 상세 정보를 확인하는 명령이다.
# 네트워크 상세 정보 표시
$ docker network inspect web-network
네트워크를 삭제하려면 그 전에 연결 중인 모든 컨테이너와의 연결을 해제해야 한다.
# 네트워크 삭제
$ docker network rm web-network
가동 중인 컨테이너에 연결하는 명령이다.
# /bin/bash가 실행되고 있는 sample이라는 이름의 컨테이너에 연결
$ docker container attach sample
[root@5f193522a67e /]#
가동 중인 컨테이너에 새로운 프로세스를 실행하는 명령이다. 웹 서버와 같이 백그라운드에서 실행되고 있는 컨테이너에 액세스하고 싶을 때, docker container attach 명령으로 연결해도 쉘이 작동하지 않는 경우는 명령을 접수할 수 없다. 이 때, docker container exec 명령을 사용하여 임의의 명령을 실행한다. docker container exec 명령은 실행 중인 컨테이너에서만 실행할 수 있다.
$ docker container run -d --name=webserver -p 8080:80 nginx
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53a9687ef00e nginx "/docker-entrypoint.…" 42 seconds ago Up 42 seconds 0.0.0.0:8080->80/tcp webserver
# 컨테이너에서 bash 실행
$ docker container exec -it webserver /bin/bash
root@53a9687ef00e:/#
# 컨테이너에서 echo 실행
$ docker container exec -it webserver /bin/echo "Hello world"
Hello world
# 프로세스 확인
$ docker container top
# 컨테이너의 포트 전송
# 'webserver' 컨테이너의 80번 포트가 호스트의 8080번 포트로 전송되는 것을 확인
$ docker container port webserver
80/tcp -> 0.0.0.0:8080
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53a9687ef00e nginx "/docker-entrypoint.…" 16 minutes ago Up 16 minutes 0.0.0.0:8080->80/tcp webserver
# 컨테이너의 이름 변경
$ docker container rename webserver new-webserver
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53a9687ef00e nginx "/docker-entrypoint.…" 16 minutes ago Up 16 minutes 0.0.0.0:8080->80/tcp new-webserver
# webserver라는 이름의 컨테이너 안에 있는 /etc/nginx/nginx.conf 파일을 호스트의 /tmp/etc에 복사할 때
$ docker container cp webserver:/etc/nginx/nginx.conf /tmp/nginx.conf
$ ls -la /tmp/nginx.cong
# 호스트의 현재 디렉토리에 있는 local.txt라는 이름의 파일을 webserver라는 이름의 컨테이너 안의 /tmp/local.txt로 복사할 때
$ docker container cp ./local.txt webserver:/tmp/local.txt
컨테이너 안에서 어떤 조작을 한 후, 컨테이너가 이미지로부터 생성되었을 때와 달라진 점(차분)을 확인하기 위한 명령이다.
$ docker container run -itd --name=sample ubuntu
# 컨테이너에서 신규 사용자 작성
$ docker container exec -it sample /bin/bash
root@5d55fed79b08:/# useradd newuser
root@5d55fed79b08:/# exit
exit
# 컨테이너의 변경 부분 확인
# 명령의 결과를 통해 /etc/passwd나 /etc/group 등에 변경이 일어났다는 것을 알 수 있다.
$ docker container diff sample
C /var
C /var/log
C /var/log/faillog
C /var/log/lastlog
C /etc
C /etc/group
A /etc/group-
C /etc/subgid
C /etc/subuid
C /etc/passwd
A /etc/subuid-
C /etc/gshadow
A /etc/passwd-
C /etc/shadow
A /etc/gshadow-
A /etc/shadow-
A /etc/subgid-
C /root
A /root/.bash_history
Docker 컨테이너는 Docker 이미지를 바탕으로 작성하지만, 반대로 Docker 컨테이너를 바탕으로 Docker 이미지를 작성할 수도 있다.
# 컨테이너로부터 이미지 작성
$ docker container commit -a "Titu" sample tituvely/webserver:1.0
sha256:f5b5ce23d6472c67e79145d38d7662de9be2936470c88444abc8d5c62aae90c5
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
tituvely/webserver 1.0 f5b5ce23d647 19 seconds ago 73.1MB
# 이미지 상세 정보 확인
# 설정한 작성자 정보를 확인할 수 있다.
$ docker image inspect tituvely/webserver:1.0
~ 생략
"DockerVersion": "17.12.0-ce",
"Author": "Titu",
~ 생략
$ docker container export sample > latest.tar
$ ls -la
total 73716
drwx------ 4 root root 4096 Jul 21 09:09 .
drwxr-xr-x 22 root root 4096 Feb 24 2018 ..
-rw-r--r-- 1 root root 3122 Feb 24 2018 .bashrc
drwx------ 2 root root 4096 Jul 21 08:56 .cache
-rw-r--r-- 1 root root 0 Feb 24 2018 .hushlogin
-rw-r--r-- 1 root root 75457024 Jul 21 09:09 latest.tar
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
drwxr-xr-x 2 root root 4096 Feb 24 2018 .ssh
# 생성된 tar 파일의 상세 정보 확인
$ tar -tf latest.tar
$ tar tf latest.tar |more
# latest.tar로 모아놓은 디렉토리나 파일을 바탕으로 tituvely/webserver라는 이름의 태그명이 1.1인 이미지를 작성한다.
$ cat latest.tar | docker image import - tituvely/webserver:1.1
sha256:6f310930b06a9f9cd2d9993abacf9e2d30a8c8746b089d664bbd19a0538529ac
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
tituvely/webserver 1.1 6f310930b06a 7 seconds ago 73.1MB
tituvely/webserver 1.0 f5b5ce23d647 21 minutes ago 73.1MB
Docker 이미지를 tar 파일로 저장할 수 있다.
# tensorflow/tensorflow라는 이름의 이미지를 export.tar에 저장한다
$ docker image save -o export.tar tensorflow/tensorflow
$ ls -l
total 1367524
-rw------- 1 root root 1324875776 Jul 21 09:34 export.tar
tar 이미지로부터 이미지를 읽어 들이는 명령이다.
# export.tar라는 이름의 이미지를 읽어들인다
$ docker image load -i export.tar
사용하지 않는 이미지, 컨테이너, 볼륨, 네트워크를 일괄적으로 삭제하는 명령이다.
# 불필요한 리소스 삭제
$ docker system prune -a
$ docker container run -itd --name="sample" nginx
$ docker container export sample > export.tar
$ tar xvf export.tar
$ ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc export.tar home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
$ docker image pull nginx
$ docker image save -o save.tar nginx
$ tar xvf save.tar
$ ls
3c3a333cdf8c89b9396046da92a7bf6a19b43a504c27ed45ca4b7103c5fff4a2 7a2bb957c3e5ab2cbb17641fb45d84c4db95409b257f3d3a3344884e0267fe78 repositories
4cdc5dd7eaadff5080649e8d0014f2f8d36d4ddf2eff2fdf577dd13da85c5d2f.json 99822641346ab3f492352d3e866bee8d4f7a555fceb6f7dc216f7ec24fa6f19d save.tar
60bf9b686621b4f7c2fe99054209c446b1c94522e61c2fbcd0025544e2b5b50d f4cb2c3fcbf290613eb42a3882b2cb60155ceb72532114422c040021d93bbc80
6ad1e4ec9a1cdc46ae489465c50471ed690e526d212c3b9f944c5949823b8e82 manifest.json
=> 바탕이 되는 이미지는 똑같아도 docker container export 명령과 docker image save 명령은 내부적인 디렉토리와 파일 구조가 다르므로, docker container export 명령으로 작성한 것을 읽어 들일 때는 docker image import 명령을, docker image save 명령으로 생성한 것을 읽어 들일 때는 docker image load 명령을 사용해야 한다.
docker container export <-> docker image import
docker image save <-> docker image load
본문은 'Asa Shijo, <완벽한 IT 인프라 구축을 위한 Docker>, 정보문화사(2020)' 를 참고하여 정리한 글입니다.
[참고: 완벽한 IT 인프라 구축을 위한 Docker]