도커 기초편
이 도구를 실제로 활용하려면 컨테이너와 이미지의 차이를 이해해야 하고, Dockerfile을 사용해 이미지 만드는 법을 익힐 필요가 있다.
개발 환경이자 배포 도구로써 도커를 이해하기 위한 개념 및 자주 사용하는 명령어을 소개하고 애플리케이션을 도커로 이미지화하는 부분까지 적어놨다.
스크립트를 사용해 정식 릴리즈된 도커 최신 버전을 설치해보기.
$ curl -s https://get.docker.com | sudo sh
버전확인
$ docker -v
Docker version 19.03.8, build afacb8b7f0
스크립트로 도커 설치를 하고 나면 /etc/apt/sources.list.d/docker.list가 추가된 것을 볼 수 있다.
$ cat /etc/apt/sources.list.d/docker.list
deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable
그리고 dpkg 명령어로 설치된 패키지 중에서 docker 이름이 들어간 패키지를 찾아보면 docker-ce와 docker-ce-cli가 설치된 것을 확인할 수 있다.
$ dpkg --get-selections | grep docker
docker-ce install
docker-ce-cli
도커에서는 docker pull <IMAGE_NAME> 명령어로 이미지를 풀 받을 수 있다.
$ docker pull centos
다운 받은 이미지를 확인
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 470671670cac 8 weeks ago 237MB
도커에서는 이미지를 다운 받을 때 install이나 download와 같은 명령 대신 pull을 사용한다.
앞으로 살펴보겠지만 이는 단순히 이미지를 다운로드 받는 데서만 그런 것이 아니라
이미지를 업로드 할 때는 push라는 명령어를 쓰고, 새로운 이미지를 생성할 때는 commit, 이미지의 차이를 확인할 때는 diff라는 명령어를 사용한다.
(마치 git 명령어와 비슷하다)
도커에서 제공하는 이미지 호스팅 서비스 도커 허브 ( 이미지를 다운받고 올릴수 있음 )
docker info를 통해서 클라이언트에 지정된 기본 레지스트리의 주소를 확인할 수 있다.
$ docker info | grep Registry
Registry: https://index.docker.io/v1/
컨테이너는 docker run를 통해서 실행할 수 있다. 여기서는 셸을 실행하기 위해서 -it를 옵션을 붙이고
docker run -it <이미지이름:태그> <명령어>로 centos 이미지 기반의 컨테이너를 하나 실행시킨다.
(호스트OS와 격리된 환경에서 bash 프로그램을 실행했다고 이해하면 된다.)
$ docker run -it centos:latest bash
[root@d3fef9c0f9e9 /]#
여기서 핵심키워드를 짚고 넘어가면,
이미지는 어떤 환경이 구성되어있는 상태를 저장해놓은 파일들의 집합이고, 컨테이너는 이 파일들의 집합 위에서 실행된 특별한 프로세스라고 생각하면 된다.
docker run -it centos:latest bash 명령어는 centos:latest 이미지로부터 bash를 실행하라는 의미이다.
(이미지 이름은 :을 구분자로 이미지 이름과 태그로 구분된다. 태그를 지정하지 않으면 기본값으로 latest가 사용된다. 따라서 centos는 centos:latest와 같다 )
--rm 플래그를 추가해주면 컨테이너가 종료 상태가 되면 자동으로 삭제를 해주는 옵션이다.
만약, 아직 이미지가 없다면, 도커의 공식 저장소에서 이 이미지를 풀을 받아오고, 그리고 이 이미지를 기반으로 bash 프로세스를 실행한다.
별도로 서버를 띄워 해당 명령어를 입력하여 현재 실행중인 모든 컨테이너 목록을 출력할 수 있다.
$ sudo docker ps
sudo를 사용하지 않으려면, 사용자 계정에서도 도커를 직접 사용할 수 있도록 docker 그룹에 사용자를 추가해준다.(이 때 관리자 권한이 필요)
$ sudo usermod -aG docker $USER
$ sudo su - $USER
컨테이너는 독립된 환경에서 실행되지만, 컨테이너의 기본적인 역할은 이미지 위에서 미리 규정된 명령어를 실행하는 일이다.
이 명령어가 종료되면 컨테이너도 종료 상태(Exit)에 들간다. 이러한 죽은 컨테이너의 목록까지 확인하려면 docker ps -a 명령어를 사용하면 된다.
exit 명령어로 셸을 종료
root@65d60d3dd306:/# exit
컨테이너가 종료되었는지 docker ps를 통해서 살펴보자(컨테이너는 배시 셸 프로세스이기 때문에, 셸을 종료하면 컨테이너도 종료된다는 점)
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
start 명령어를 통해 이미지를 되살릴 수 있다.
$ docker restart d3fef9c0f9e9
컨테이너로 실행된 프로세스와 터미널 상에서 입출력을 주고 받으려면 attach 명령어를 사용해야한다.
$ docker attach d3fef9c0f9e9
[root@d3fef9c0f9e9 /]#
이 외에도 실행된 컨테이너를 강제로 종료시키는 stop 명령어가 있으며,
종료된 컨테이너를 삭제하는 rm 명령어도 있다.
이제 컨테이너에 Git을 설치해보자. 먼저 이 우분투 기본 이미지에는 깃이 설치되어있지 않다는 것을 확인해보자.
root@65d60d3dd306:/# git --version
bash: git: command not found
그 전에, 이 컨테이너의 부모 이미지 간의 파일 변경사항을 확인할 수 있는 명령어가 있다.
git diff 명령어로 프로젝트의 변경사항을 확인하듯이, docker diff 명령어로 부모 이미지와 여기서 파생된 컨테이너의 파일 시스템 간의 변경사항을 확인할 수 있다.
우분투에 셸이 실행된 컨테이너를 그대로 두고, 다른 셸에서 docker diff 명령어를 실행해보자.
$ dockre ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
65d60d3dd306 ubuntu:bionic "bash" About a minute ago Up About a minute distracted_ardinghelli
$ dokcker diff 65d60d3dd306
(아무것도 출력안함 왜냐하면 이 컨테이너는 깃을 설치하지 않은 아직 이미지 파일 시스템 상태 그대로이기 때문)
이제 깃을 설치한다.
root@65d60d3dd306:/# apt update
...
root@65d60d3dd306:/# apt install -y git
...
root@65d60d3dd306:/# git --version
git version 2.17.1
다시 셸을 그대로 두고 다른 셀에서 diff를 다시 실행해보자.
$ docker diff 65d60d3dd306 | head
C /usr
C /usr/lib
A /usr/lib/ssl
A /usr/lib/ssl/certs
A /usr/lib/ssl/misc
A /usr/lib/ssl/misc/CA.pl
A /usr/lib/ssl/misc/tsget
A /usr/lib/ssl/misc/tsget.pl
A /usr/lib/ssl/openssl.cnf
A /usr/lib/ssl/private
: 많은 결과가 생성된다. 너무 많기 때문에 head로 앞부분만 출력하도록 하여 살펴보자 (여기서 A는 ADD, C는 Change, D는 Delete를 의미한다.)
이제 ubuntu:bionic 이미지에 깃이 설치된 새로운 이미지를 생성해보도록하겠다. 도커에서는 이 작업을 commit이라고 한다.
(커밋을 하고 뒤에 이름을 붙여주면 바로 새로운 도커 이미지가 생성된다.)
$ docker commit 65d60d3dd306 ubuntu:git
sha256:12924460218feb38da74e9a64c95acd55d16297346b2698f47f396936636c93d
$ REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu git 12924460218f 4 seconds ago 186MB
ubuntu bionic 4e5021d210f6 8 hours ago 64.2MB
centos latest 470671670cac 2 months ago 237MB
이 이미지를 통해서 컨테이너를 실행하면 git이 설치되어 있는 것을 확인 할 수 있다.
$ docker run -i -t ubuntu:git bash
root@2a00b9b2b7cc:/# git --version
git version 2.17.1
root@2a00b9b2b7cc:/# exit
필요없는 이미지를 삭제시 주의사항
ubuntu:git를 삭제한다고 하면, 이미지에서 파생된 (종료 상태를 포함한) 컨테이너가 하나라도 남아있다면 이미지는 삭제할 수 없다.
따라서 먼저 컨테이너를 종료하고, 삭제까지 해주어야한다.
docker rm은 컨테이너를 삭제하는 명령어이고, docker rmi는 이미지를 삭제하는 명령어이다.
먼저 컨테이너를 지우고, 이미지를 삭제한다.
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a00b9b2b7cc ubuntu:git "bash" 2 minutes ago Exited (130) 3 seconds ago cranky_franklin
$ docker rm 2a00b9b2b7cc
2a00b9b2b7cc
$ docker rmi ubuntu:git
Untagged: ubuntu:git
Deleted: sha256:487a3619305e68483059caa21eb54d1d812ced4282df9e2ba05ec46ed9a2b8f4
Deleted: sha256:9b6621e819f094c16ea9f63af90f7cb564a48133c05504fad0f28563865f957d
여기까지 도커 이미지의 생명주기를 배웠다.
도커 이미지를 pull로 받아오고 commit으로 새로운 이미지를 만들고 rmi 명령어로 삭제해보았다.
이제 남은 일은 자신에게 필요한 이미지를 만들고 이 이미지를 통해서 컨테이너를 실행하는 일이다.
그리고 이제 기본적인 개념들을 배웠으니 중앙 저장소인 도커 허브에서 이미 만들어져있는 다양한 이미지들을 활용할 수도 있다.
도커 이미지를 추가하는 방법은 크게 세 가지가 있다.
1. 앞서 봤던, pull을 사용해 미리 만들어져있는 이미지를 가져오는 방법
2. 앞서 봤던, 컨테이너의 변경사항으로부터 이미지를 만드는 법
3. Dockerfile을 빌드하는 방법. (Dockerfile은 도커만의 특별한 DSL로 이미지를 정의하는 파일이다.)
Dockerfile을 저장해놓기 위한 디렉터리를 하나 만든다
$ mkdir git-from-dockerfile
$ cd git-from-dockerfile
Dockerfile을 작성
FROM ubuntu:bionic
RUN apt-get update
RUN apt-get install -y git
작성한 내용의 키워드를 살펴보자
먼저 FROM은 어떤 이미지로부터 이미지를 생성할지 지정한다.
Dockerfile에서는 필수 항목이며, 여기서는 ubuntu:bionic을 지정한다.
다음으로 RUN 지시자는 명령어를 실행하라는 의미이다.
먼저 apt-get update를 실행하고, 다음으로 apt-get install -y git을 실행한다.
이 Dockerfile로 이미지를 빌드를 한다.
$ docker build -t ubuntu:git-from-dockerfile .
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM ubuntu:bionic
---> 4e5021d210f6
Step 2/3 : RUN apt-get update
...
---> c2110a74f55e
Step 3/3 : RUN apt-get install -y -qq git
...
---> cc770735315e
Successfully built cc770735315e
Successfully tagged ubuntu:git-from-dockerfile
그럼 새로 만든 이미지에 Git이 잘 설치되었는지 확인해보자.
$ docker run -it ubuntu:git-from-dockerfile bash
root@f98f0bd06b67:/# git --version
git version 2.17.1
설치가 된 걸 확인할 수 있다.
좀 더 응용해서, 도커파일을 작성해보자
이번에는 웹 애플리케이션 서버를 실행하기 위한 도커 이미지를 작성해보자.
예제로 사용해볼 웹 애플리케이션은 PHP와 아파치 서버를 기반으로 동작하는 모니위키다.
(애플리케이션 실행을 위해 도커 이미지를 만드는 작업을 도커라이징 Dockerizing이라고도 한다.)
여기서는 미리 만들어둔 Dockerfile의 내용을 보고 내용을 같이 살펴보기로 한다.
먼저 깃으로 예제 도커파일 저장소를 클론 받는다
$ git clone https://github.com/nacyot/docker-moniwiki.git
$ cd docker-moniwiki/moniwiki
디렉터리에 포함된 Dockerfile의 내용에 대해서 살펴본다.
FROM ubuntu:14.04
RUN apt-get update &&\
apt-get -qq -y install git curl build-essential apache2 php5 libapache2-mod-php5 rcs
WORKDIR /tmp
RUN \
curl -L -O https://github.com/wkpark/moniwiki/archive/v1.2.5p1.tar.gz &&\
tar xf /tmp/v1.2.5p1.tar.gz &&\
mv moniwiki-1.2.5p1 /var/www/html/moniwiki &&\
chown -R www-data:www-data /var/www/html/moniwiki &&\
chmod 777 /var/www/html/moniwiki/data/ /var/www/html/moniwiki/ &&\
chmod +x /var/www/html/moniwiki/secure.sh &&\
/var/www/html/moniwiki/secure.sh
RUN a2enmod rewrite
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
EXPOSE 80
CMD bash -c "source /etc/apache2/envvars && /usr/sbin/apache2 -D FOREGROUND"
: Dockerfile의 한 줄 한 줄은 레이어라는 형태로 저장되기 때문에 RUN을 줄이면 레이어가 줄어들고, 캐시도 효율적으로 관리할 수 있다.
여기서 &&은 여러 명령어를 이어서 실행하기 위한 연산자이고, \은 명령어를 여러줄에 작성하기 위한 문자이다.
이는 Dockerfile을 작성할 때 자주 사용되는 패턴이니, 여러 명령어를 이어 붙일 때 RUN 하나에 &&\로 나눠 여러 명령어를 실행하는 데 사용한다고 기억해두면 도움이 되겠다.
WORKDIR /tmp 이 지시자는 이후에 실행되는 모든 작업의 실행 디렉터리를 변경한다.
리눅스 명령어로 생각해보면 cd라고 생각할 수 있다. RUN 명령어를 실행할 때 앞에 매번 cd를 붙여줄 수도 있지만, 매번 실행 위치가 초기화되기 때문에 WORKDIR을 사용하면 작업할 때 좀 더 편리하다.
여기서는 깃허브 GitHub 저장소에 릴리스되어있는 모니위키를 다운로드 받아 Apache2로 동작하도록 셋업한다.
첫 번째 RUN은 모니위키를 셋업하는 내용이다. 여기서도 RUN 하나에 여러 명령어들을 &&로 연결해주었다. 조금 길어보이지만, 기본적인 리눅스 명령어들로 구성되어있다.
PHP 코드의 압축을 풀고, 아파치가 접근하는 디렉터리로 복사하고 접근 권한을 설정한다.
두 번째 RUN은 아파치2의 모듈을 활성화하는 내용이다
ENV는 컨테이너 실행 환경에 적용되는 환경변수의 기본값을 지정하는 지시자이다.
리눅스에서는 환경변수로 애플리케이션의 동작을 제어하는 경우가 자주 있기에 도커에서는 이러한 방식을 권장하는 편이며, 직접 애플리케이션을 작성하는 경우에도 환경변수로 설정값을 넘겨받아 처리할 수 있도록 코딩한다.
(여기서는 아파치에서 사용하는 APACHE_RUN_USER, APACHE_RUN_GROUP, APACHE_LOG_DIR 환경변수를 정의했다)
EXPOSE는 가상머신에 오픈할 포트를 지정해준다.
마지막 줄의 CMD에는 컨테이너에서 실행될 명령어를 지정해준다.
이 글의 앞선 예 에서는 docker run을 통해서 bash를 실행했지만, 여기서는 아파치 서버를 FOREGROUND에 실행을 했다.(이 명령어는 기본값이고 컨테이너 실행시에 덮어쓸 수 있다)
이제 직접 이 Dockerfile을 빌드할 차례이다.
(nacyot는 사용자가 지정한 네임스페이스라고 생각하면 된다.)
$ docker build -t nacyot/moniwiki:latest .
Sending build context to Docker daemon 7.68kB
Step 1/10 : FROM ubuntu:14.04
---> 6e4f1fe62ff1
Step 2/10 : RUN apt-get update && apt-get -qq -y install git curl build-essential apache2 php5 libapache2-mod-php5 rcs
...
---> becdcac5d788
Step 3/10 : WORKDIR /tmp
...
---> dbdc86a08299
Step 4/10 : RUN curl -L -O https://github.com/wkpark/moniwiki/archive/v1.2.5p1.tar.gz && tar xf /tmp/v1.2.5p1.tar.gz && mv moniwiki-1.2.5p1 /var/www/html/moniwiki && chown -R www-data:www-data /var/www/html/moniwiki && chmod 777 /var/www/html/moniwiki/data/ /var/www/html/moniwiki/ && chmod +x /var/www/html/moniwiki/secure.sh && /var/www/html/moniwiki/secure.sh
...
---> 48926b3b3da0
Step 5/10 : RUN a2enmod rewrite
...
---> 98a0ed3df283
Step 6/10 : ENV APACHE_RUN_USER www-data
...
---> a1f1247b98cb
Step 7/10 : ENV APACHE_RUN_GROUP www-data
...
---> dee2cb60f1cc
Step 8/10 : ENV APACHE_LOG_DIR /var/log/apache2
...
---> df4bd9e4dd7e
Step 9/10 : EXPOSE 80
...
---> f68911b22856
Step 10/10 : CMD bash -c "source /etc/apache2/envvars && /usr/sbin/apache2 -D FOREGROUND"
...
---> 408c35f3d162
Successfully built 408c35f3d162
Successfully tagged nacyot/moniwiki:latest
도커 파일을 한 단계 씩 빌드해가며 이미지가 만들어지는 과정을 확인할 수 있다.
이제 모니위키를 실행을 해보자.
docker run을 실행하며 이번에는 -d와 -p 플래그를 사용한다. -d 플래그는 -i의 반대 역할을 하는 옵션으로, 컨테이너를 백그라운드에서 실행하고,-p는 포트포워딩을 지정하는 옵션이다.
:을 경계로 앞에는 외부 포트, 뒤에는 컨테이너 내부 포트를 지정한다.
참고로 컨테이너 안에서 아파치가 80포트로 실행된다. 따라서 여기서는 9999로 들어오는 연결을 컨테이너에서 실행된 서버의 80포트로 보낸다
$ docker run -d -p 9999:80 nacyot/moniwiki:latest
746443ad118afdb3f254eedaeeada5abc2b125c7263bc5e67c2964b570166187
로컬 머신의 9999 포트에 접근해 모니위키 서버가 잘 실행중인지 살펴보면 나오는 것을 확인할 수 있다.
http://127.0.0.1:9999/moniwiki/monisetup.php
여기서는 사실상 미리 만들어진 Dockerfile을 예제로 사용했다. 원래 처음 Dockerfile을 작성할 때는 빈 파일에서 시작해야한다.
FROM으로 시작하고, 그 다음에는 주로 RUN을 사용해 리눅스 명령어를 사용하듯이 환경을 구축해나간다.
가장 중요한 작업은 패키지 관리자로 애플리케이션 실행 환경을 구축하고, 실행할 애플리케이션을 다운로드 받거나 복사하는 작업이다.
이 예제에서는 도커 빌드 과정에서 온라인 상의 모니위키 소스코드를 다운로드 받았지만, 직접 작성하는 애플리케이션의 경우 COPY나 ADD 지시자를 사용해 로컬 파일을 복사하는 방법을 주로 사용한다.
여기서는 다루지 않은 지시자들도 있지만 대부분의 경우 FROM, RUN, WORKDIR, ADD, CMD 정도면 원하는 이미지를 만들 수 있다.
Dockerfile을 처음부터 완성하기보다는 중간중간 빌드하면서 작업하는 것을 추천한다.
도커는 도커 이미지 빌드 과정을 캐시하기 때문에 내용이 변하지 않은 부분까지는 빠르게 빌드가 이루어진다.
도커의 이미지 빌드 과정
앞서 도커 빌드를 할 때 도커 파일을 할 줄씩 빌드하는 것을 확인할 수 있다.
도커 파일에서 FROM, RUN, WORKDIR 같은 지시자 하나 하나가 바로 스탭이 되며, 도커는 FROM에 지정된 이미지에서 부터 시작합니다.
이 이미지로 컨테이너를 만들고, 다음 지시자의 명령을 수행한다.
그리고 이 내용을 도커 이미지로 저장한다.
예를 들어 다음 지시자가 RUN이라면 명령어를 실행하고 이를 이미지로 만든다.
그리고 이렇게 만들어진 이미지를 기반으로 다음 지시자를 실행한다.
즉, 스탭 하나를 빌드할 때마다, 1. 컨테이너 생성, 2. 지시자 실행, 3. 임시 이미지 생성 과정을 거친다.
이 과정을 Dockerfile의 지시자수(즉, 스탭 수)만큼 반복한다.
(빌드는 비유하자면, 최신 업데이트라 보면 되겠다)
위에서 직접 만든 도커 이미지는 아래 명령어 하나로 실행할 수 있다.
$ docker run -d -p 9999:80 nacyot/moniwiki:latest
이 이미지를 다른 서버에서도 쉽게 사용할 수 있을까? 가상 서버를 한 대 만들어서 온라인 상에 모니위키를 배포해보겠다.
도커 허브 docker info 명령어로 확인(도커 클라이언트는 기본적으로 도커 허브를 사용합니다. 출력 결과에 보이는 https://index.docker.io/v1/이 도커 허브의 API 서버 주소다.)
$ docker info | grep Registry
Registry: https://index.docker.io/v1/
도커 허브는 공식 이미지를 풀 받는 데 사용할 수도 있지만, 직접 만든 이미지를 올리거나 배포하는 데도 사용할 수 있다.
퍼블릭 도커 이미지의 경우는 무료로 제공되며, 프라이빗 이미지를 사용하는 경우 비용이 발생한다.
도커 허브를 사용하려면 먼저 회원 가입을 진행해야한다.
계정을 생성하고 나면 도커 클라이언트를 사용해 로그인할 수 있다.
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: <DOCKER_HUB_ID>
Password:
WARNING! Your password will be stored unencrypted in /home/vagrant/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
앞서 모니위키 이미지 이름을 nacyot/moniwiki:latest라고 지었는데, 여기서 nacyot은 네임스페이스에 해당하는 부분으로 도커 허브에서는 사용자 이름을 의미한다.
즉, 자신의 아이디로 이미지 이름을 변경해준다.
$ docker tag nacyot/moniwiki:latest <DOCKER_HUB_ID>/moniwiki:latest
이름이 변경되었으면 바로 이미지를 푸시한다. 푸시한 이미지는 공개 저장소로 등록된다.
$ docker push <DOCKER_HUB_ID>/moniwiki:latest
이름 규칙만 맞으면 도커 허브는 아직 <DOCKER_HUB_ID>/moniwiki 이미지 저장소가 없더라도, 푸시 작업 과정에서 이미지 저장소를 생성해준다.
도커 허브에서도 푸시한 이미지를 확인할 수 있다. 이제 로컬에서 이 이미지를 삭제하더라도 도커 허브에서 다시 풀 받을 수 있고,다른 서버에서 이 이미지를 풀 받아 실행하는 것도 가능하다
새로 생성한 서버에 접속하여 도커를 설치하고 해당 이미지로 컨테이너 실행하면 새로운 서버에서도 사용가능하다
$ docker run -d -p 9999:80 <DOCKER_HUB_ID>/moniwiki:latest
새로운 서버에도 적용이 된 것을 확인 할 수 있다.
ubuntu:bionic 이미지의 풀네임은 docker.io/library/ubuntu:bionic 이다. docker pull 명령어로 한 번 확인해본다
$ docker pull docker.io/library/ubuntu:bionic
bionic: Pulling from library/ubuntu
Digest: sha256:bec5a2727be7fff3d308193cfde3491f8fba1a2ba392b7546b43a051853a341d
Status: Image is up to date for ubuntu:bionic
docker.io/library/ubuntu:bionic
이미지가 정상적으로 풀 되는 것을 알 수 있다. 이미지의 풀네임은 크게 4부분으로 구성되어있다.
맨 앞의 docker.io는 도커 레지스트리의 서버 주소이다.
슬래시로 구분된 library는 네임스페이스이다.
도커 허브의 경우 네임스페이스가 곧 사용자 이름이기도 하다.
(library는 도커 공식 이미지를 제공하는 특별한 네임스페이스이다)
다음 슬래시 다음에 오는 문자열이 이미지 고유의 이름이다.
그리고 : 뒤에는 추가적으로 이미지를 구분해주기 위한 태그가 따라온다.
하나의 이미지 저장소는 태그가 다른 다수의 이미지를 가질 수 있다.
도커 클라이언트에서는 편의상 docker.io/를 생략하더라도 기본 레지스트리 서버로 사용한다.