반응형

Build your own images


도커 이미지는 컨테이너의 기반이다. docker run을 실행할때마다 어떠한 이미지를 원하는지 기술해야 된다. 이전 섹션에서는 이미 존재하는 이미지를 사용하는 방법에 대해서 알아봤다.


우리는 또한 도커 호스트에 다운로드된 이미지가 저장된다는 것도 알고 있다. 만약 호스트에 이미지에 존재한다면 레지스트리로 부터 다운로드 받지 않는다 : 기본적으로 Docker Hub 레지스트리이다.


이번 섹션에서는 도커 이미지에 대해서 더 많은 것을 알아 볼 것이다.

  • 도커 호스트의 이미지 관리하고 사용하기
  • 기본 이미지 생성
  • 도커허브 레지스트리로 이미지 업로드하기


Listing images on the host


호스트에 있는 이미지를 리스팅하는 걸로 시작해보자. 커맨드는 다음과 같다.

$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

docker-whale        latest              e6181174002b        5 weeks ago         274.3 MB

ubuntu              latest              8693db7e8a00        7 weeks ago         187.9 MB

hello-world         latest              af340544ed62        7 months ago        960 B

devsun98/whalesay   latest              fb434121fc77        9 months ago        247 MB

docker/whalesay     latest              fb434121fc77        9 months ago        247 MB

training/webapp     latest              02a8815912ca        10 months ago       348.8 MB


리스트에서 우리는 다음과 같은 정보를 얻을 수 있다.

  • 어느 리파지토리부터 다운로드 되었는지
  • 각 이미지의 태그
  • 각 이미지의 이미지 아이디


리파지토리는 이미지의 다양한 버젼을 포함하고 있다. 이 경우 우분투 이미지는 다양한 Ubuntu 10.04, 12.04, 12.10, 13.04, 13.10 and 14.0를 커버한다. 각 종류는 태그에 의해 식별되며 이미지 태그는 다음과 같이 언급할 수 있다.


ubuntu:14.04


그래서 특정한 태그의 이미지로 컨테이너를 생성할려면 다음과 같다.

$ docker run -t -i ubuntu:14.04 /bin/bash


만약 대신에 12.04 이미지를 사용한다면 다음과 같이 명령하면 된다.

$ docker run -t -i ubuntu:12.04 /bin/bash


만약 태그를 명시하지 않으면 기본적으로 ubuntu:default 이미지를 사용한다.


Tip: 정확한 이미지의 종류를 사용하기 위해선 이미지 태그를 반드시 명시하자. 이것이 트러블슈팅과 디버깅에 유용하다.


Getting a new image


어떻게 새로운 이미지를 가지냐고? 도커는 도커 호스트에 사용할 이미지가 존재하지 않는다면  자동으로 다운로드를 받는다. 그러나 컨테이너를 나중에 띄우고 이미지를 먼저 저장하고 싶을때는 docker pull 커맨드를 사용하면 된다. 만약 centos 이미지를 다운로드 받고 싶다고 가정해보자.

$ docker pull centos

Using default tag: latest

latest: Pulling from library/centos

47d44cb6f252: Pull complete

6fdebd7b0eb5: Pull complete

a63aae4d216f: Pull complete

bb3d629a7cbc: Pull complete

library/centos:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.

Digest: sha256:381f21e4c7b3724c6f420b2bcfa6e13e47ed155192869a2a04fa10f944c78476

Status: Downloaded newer image for centos:latest


이미지의 각 레이어가 다운로드 괸 것을 알 수 있고 이제 우리는 이미지로부터 컨테이너를 실행할 수 있다. 

$ docker run -t -i centos /bin/bash

bash-4.1#


Finding images


도커의 하나의 특징은 수 많은 사람들이 다양한 목적으로 만든 이미지를 가지고 있다는 것이다. 이들중 많은 이미지들이 도커허브에 업로드되어 있다. 우리는 이러한 이미지들을 도커 허브 웹사이트에서 검색할 수 있다. 





또한 docker search 커맨드로 이미지를 찾을 수도 있다. 만약 팀이 ruby와 sinatra가 설치된 이미지를 원한다고 가정해보자. 다음과 같은 커맨드로 sinatra라는 단어가 들어가 모든 이미지를 검색할 수 있다.


$ docker search sinatra

NAME                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED

erikap/ruby-sinatra                    Docker for hosting Sinatra apps                 5                    [OK]

semtech/mu-sinatra-template            Template for running Sinatra microservices      1                    [OK]

lucymhdavies/sinatra-boilerplate       Docker image with my boilerplate for Sinat...   1                    [OK]

zyio/sinatra                           Tiny-ish Sinatra Dockerfile                     1                    [OK]

tdiary/rpaproxy-sinatra                                                                1                    [OK]

sashaegorov/docker-alpine-sinatra      Alpine Sinatra is project for running a Si...   0                    [OK]

. . .


sinatra라는 단어를 사용하는 많은 이미지가 조회된다. 우리는 다양한 정보를 얻을 수 있는데 이름, 설명, 별점, 공식, 자동화된 빌드 상태이다. 공식 리파지토리는 도커 회사에 의해 세심하게 관리된다. 자동화된 리파지토리는 이미지의 소스와 내용을 검증하기 위해 자동화된 빌드가 허용된다.


우리는 training/sinatra 이미지를 사용하도록 결정했다. 현재까지 우리는 두가지 타입의 이미지를 보았다. 하나는 ubuntu와 같이 베이스 혹은 루트라고 불리는 이미지이다. 베이스 이미지는 도커 Inc로부터 제공되고 빌드되고, 검증되고 지원된다. 이러한 이미지들은 하나의 단어로 된 이름을 가지고 있다.


우리는 이미 유저 이미지를 보았다. 유저 이미지는 도커 커뮤니티의 유저에 의해서 관리되고 빌드되고 유지된다.  유저 이미지는 유저이름이 접두어로 사용된다. 여기서 training은 해당 이미지를 만든 유저의 명이다.


Pulling our image


적당한 이미지를 찾았다면 docker pull 커맨드로 다운로드를 받아보자.

$ docker pull training/sinatra


우리는 이제 컨테이너를 실행할 때 이 이미지를 사용할 수 있다.


Creating our own images


우리 팀은 training/sinatra 이미지가 꽤 유용하다는 걸 알았다 그러나 약간의 변경이 필요하다는 사실도 알게되었다. 이럴경우 우리는 이미지를 업데이트하거나 생성할 수 있다.

  • 우리는 해당 이미지로 부터 생성된 컨테이너를 업데이트 하고 그 결과를 이미지에 커밋할 수 있다.
  • 우리는 Dockerfile을 사용하여 이미지를 생성하기 위한 명시적인 지시를 할 수 있다.


Updating and committing an image


이미지를 업데이트하기 위해 먼저 이미지로부터 컨테이너를 생성할 필요가 있다.

$ docker run -t -i training/sinatra /bin/bash

root@c30555556930:/#


Note: 컨테이너 ID는 c30555556930으로 생성되었고 곧 그것을 사용해야 할 것이다.


실행중인 컨테이너에 json gem을 추가해보자.

root@c30555556930:/# gem install json

Fetching: json-1.8.3.gem (100%)

Building native extensions.  This could take a while...

Successfully installed json-1.8.3

1 gem installed

Installing ri documentation for json-1.8.3...

Installing RDoc documentation for json-1.8.3...


그런 다음 exit 커맨드로 컨테이너로부터 빠져나오자.


이제 컨테이너는 변경되었다. 이제 docker commit 커맨드로 이미지에 커밋해보자.

docker commit -m "Added json gem" -a "Kate Smith" c30555556930 ouruser/sinatra:v2

04fb55e5da9f4ab45e13c5243fb5f75c5de835ca953f713d743bb94acedb8738


여기 docker commit 명령을 사용하였다. 우리는 두가지 플래그를 명시하였는데 -m과 -a이다. -m 플래그는 특정한 커밋 메시지를 남기는 것이고, -a 플래그는 업데이트를 한 저자를 명시한 것이다.


우리는 또한 특정한 컨테이너(c30555556930)로부터 새로운 이미지가 생성되었음을 명시하고 이미지를 위한 타겟을 명시하였다.

ouruser/sinatra:v2


이것을 분석해 보면 새로운 유저 ouruser를 명시하였고, 또한 새로운 이미지명도 명시한 것을 알 수 있다. 여기서는 오리지널 이미지명을 그대로 사용하였다. 그리고 이미지를 위한 태그를 명시하였는데 v2가 그것이다.


우리는 docker images 커맨드로 새로운 이미지가 생성되었음을 알 수 있다.

$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

ouruser/sinatra     v2                  04fb55e5da9f        7 minutes ago       452.4 MB

centos              latest              bb3d629a7cbc        6 days ago          196.6 MB

docker-whale        latest              e6181174002b        5 weeks ago         274.3 MB

ubuntu              latest              8693db7e8a00        7 weeks ago         187.9 MB

hello-world         latest              af340544ed62        7 months ago        960 B

devsun98/whalesay   latest              fb434121fc77        9 months ago        247 MB

docker/whalesay     latest              fb434121fc77        9 months ago        247 MB

training/webapp     latest              02a8815912ca        10 months ago       348.8 MB

training/sinatra    latest              f0f4ab557f95        21 months ago       447 MB


Building an image from a Dockerfile


docker commit 커맨드를 사용하는 것은 이미지를 확장하기 위한 매우 단순한 방법이다. 그러나 이 방법은 팀간의 이미지를 공유하기에는 쉽지 않은 방법이다. 대신에 새로운 커맨드 docker build를 통해 새로운 이미지를 생성하는 방법을 알아보자.


Dockerfile은 새로운 이미지를 빌드하기 위한 일련의 지시를 포함하고 있는 것이다.


먼저 디렉토리를 만들고 Dockerfile을 생성해보자.

$ mkdir sinatra

$ cd sinatra

$ touch Dockerfile


그리고 도커 파일에 다음과 같은 내용을 채우자.

# This is a comment

FROM ubuntu:14.04

MAINTAINER Kate Smith <ksmith@example.com>

RUN apt-get update && apt-get install -y ruby ruby-dev

RUN gem install sinatra


도커파일을 자세히 살펴보면 각 지시에 대문자로 접두어가 붙어있는 것을 알 수 있다.

INSTRUCTION statement


Note: 코멘트를 하기 위해 #을 이용할 수 있다.


첫번째 FROM 지시어는 도커에게 이미지의 소스가 무엇인지 이 경우 새로운 이미지의 베이스는 Ubuntu 14.04이다. MAINTAINER는 새로운 이미지를 유지하는 관리자를 의미한다.


마지막으로 두개의 RUN 지시자가 있다. RUN 지시자는 이미지 내부에서 커맨드를 수행한다. 여기서는 APT 캐쉬를 업데이트하고 Ruby와 RubyGems을 설치하고 Sinatra gem을 설치한다.


이제 도커파일과 docker build 커맨드를 이용해 새로운 이미지를 빌드해보자.

$ docker build -t ouruser/sinatra:v2 .

Sending build context to Docker daemon 2.048 kB

Sending build context to Docker daemon

Step 1 : FROM ubuntu:14.04

 ---> e54ca5efa2e9

Step 2 : MAINTAINER Kate Smith <ksmith@example.com>

 ---> Using cache

 ---> 851baf55332b

Step 3 : RUN apt-get update && apt-get install -y ruby ruby-dev

 ---> Running in 3a2558904e9b

Selecting previously unselected package libasan0:amd64.

(Reading database ... 11518 files and directories currently installed.)

Preparing to unpack .../libasan0_4.8.2-19ubuntu1_amd64.deb ...

Unpacking libasan0:amd64 (4.8.2-19ubuntu1) ...

Selecting previously unselected package libatomic1:amd64.

Preparing to unpack .../libatomic1_4.8.2-19ubuntu1_amd64.deb ...

Unpacking libatomic1:amd64 (4.8.2-19ubuntu1) ...

Selecting previously unselected package libgmp10:amd64.

Preparing to unpack .../libgmp10_2%3a5.1.3+dfsg-1ubuntu1_amd64.deb ...

Unpacking libgmp10:amd64 (2:5.1.3+dfsg-1ubuntu1) ...

Selecting previously unselected package libisl10:amd64.

Preparing to unpack .../libisl10_0.12.2-1_amd64.deb ...

Unpacking libisl10:amd64 (0.12.2-1) ...

Selecting previously unselected package libcloog-isl4:amd64.

Preparing to unpack .../libcloog-isl4_0.18.2-1_amd64.deb ...

Unpacking libcloog-isl4:amd64 (0.18.2-1) ...

Selecting previously unselected package libgomp1:amd64.

Preparing to unpack .../libgomp1_4.8.2-19ubuntu1_amd64.deb ...

Unpacking libgomp1:amd64 (4.8.2-19ubuntu1) ...

Selecting previously unselected package libitm1:amd64.

Preparing to unpack .../libitm1_4.8.2-19ubuntu1_amd64.deb ...

Unpacking libitm1:amd64 (4.8.2-19ubuntu1) ...

Selecting previously unselected package libmpfr4:amd64.

Preparing to unpack .../libmpfr4_3.1.2-1_amd64.deb ...

Unpacking libmpfr4:amd64 (3.1.2-1) ...

Selecting previously unselected package libquadmath0:amd64.

Preparing to unpack .../libquadmath0_4.8.2-19ubuntu1_amd64.deb ...

Unpacking libquadmath0:amd64 (4.8.2-19ubuntu1) ...

Selecting previously unselected package libtsan0:amd64.

Preparing to unpack .../libtsan0_4.8.2-19ubuntu1_amd64.deb ...

Unpacking libtsan0:amd64 (4.8.2-19ubuntu1) ...

Selecting previously unselected package libyaml-0-2:amd64.

Preparing to unpack .../libyaml-0-2_0.1.4-3ubuntu3_amd64.deb ...

Unpacking libyaml-0-2:amd64 (0.1.4-3ubuntu3) ...

Selecting previously unselected package libmpc3:amd64.

Preparing to unpack .../libmpc3_1.0.1-1ubuntu1_amd64.deb ...

Unpacking libmpc3:amd64 (1.0.1-1ubuntu1) ...

Selecting previously unselected package openssl.

Preparing to unpack .../openssl_1.0.1f-1ubuntu2.4_amd64.deb ...

Unpacking openssl (1.0.1f-1ubuntu2.4) ...

Selecting previously unselected package ca-certificates.

Preparing to unpack .../ca-certificates_20130906ubuntu2_all.deb ...

Unpacking ca-certificates (20130906ubuntu2) ...

Selecting previously unselected package manpages.

Preparing to unpack .../manpages_3.54-1ubuntu1_all.deb ...

Unpacking manpages (3.54-1ubuntu1) ...

Selecting previously unselected package binutils.

Preparing to unpack .../binutils_2.24-5ubuntu3_amd64.deb ...

Unpacking binutils (2.24-5ubuntu3) ...

Selecting previously unselected package cpp-4.8.

Preparing to unpack .../cpp-4.8_4.8.2-19ubuntu1_amd64.deb ...

Unpacking cpp-4.8 (4.8.2-19ubuntu1) ...

Selecting previously unselected package cpp.

Preparing to unpack .../cpp_4%3a4.8.2-1ubuntu6_amd64.deb ...

Unpacking cpp (4:4.8.2-1ubuntu6) ...

Selecting previously unselected package libgcc-4.8-dev:amd64.

Preparing to unpack .../libgcc-4.8-dev_4.8.2-19ubuntu1_amd64.deb ...

Unpacking libgcc-4.8-dev:amd64 (4.8.2-19ubuntu1) ...

Selecting previously unselected package gcc-4.8.

Preparing to unpack .../gcc-4.8_4.8.2-19ubuntu1_amd64.deb ...

Unpacking gcc-4.8 (4.8.2-19ubuntu1) ...

Selecting previously unselected package gcc.

Preparing to unpack .../gcc_4%3a4.8.2-1ubuntu6_amd64.deb ...

Unpacking gcc (4:4.8.2-1ubuntu6) ...

Selecting previously unselected package libc-dev-bin.

Preparing to unpack .../libc-dev-bin_2.19-0ubuntu6_amd64.deb ...

Unpacking libc-dev-bin (2.19-0ubuntu6) ...

Selecting previously unselected package linux-libc-dev:amd64.

Preparing to unpack .../linux-libc-dev_3.13.0-30.55_amd64.deb ...

Unpacking linux-libc-dev:amd64 (3.13.0-30.55) ...

Selecting previously unselected package libc6-dev:amd64.

Preparing to unpack .../libc6-dev_2.19-0ubuntu6_amd64.deb ...

Unpacking libc6-dev:amd64 (2.19-0ubuntu6) ...

Selecting previously unselected package ruby.

Preparing to unpack .../ruby_1%3a1.9.3.4_all.deb ...

Unpacking ruby (1:1.9.3.4) ...

Selecting previously unselected package ruby1.9.1.

Preparing to unpack .../ruby1.9.1_1.9.3.484-2ubuntu1_amd64.deb ...

Unpacking ruby1.9.1 (1.9.3.484-2ubuntu1) ...

Selecting previously unselected package libruby1.9.1.

Preparing to unpack .../libruby1.9.1_1.9.3.484-2ubuntu1_amd64.deb ...

Unpacking libruby1.9.1 (1.9.3.484-2ubuntu1) ...

Selecting previously unselected package manpages-dev.

Preparing to unpack .../manpages-dev_3.54-1ubuntu1_all.deb ...

Unpacking manpages-dev (3.54-1ubuntu1) ...

Selecting previously unselected package ruby1.9.1-dev.

Preparing to unpack .../ruby1.9.1-dev_1.9.3.484-2ubuntu1_amd64.deb ...

Unpacking ruby1.9.1-dev (1.9.3.484-2ubuntu1) ...

Selecting previously unselected package ruby-dev.

Preparing to unpack .../ruby-dev_1%3a1.9.3.4_all.deb ...

Unpacking ruby-dev (1:1.9.3.4) ...

Setting up libasan0:amd64 (4.8.2-19ubuntu1) ...

Setting up libatomic1:amd64 (4.8.2-19ubuntu1) ...

Setting up libgmp10:amd64 (2:5.1.3+dfsg-1ubuntu1) ...

Setting up libisl10:amd64 (0.12.2-1) ...

Setting up libcloog-isl4:amd64 (0.18.2-1) ...

Setting up libgomp1:amd64 (4.8.2-19ubuntu1) ...

Setting up libitm1:amd64 (4.8.2-19ubuntu1) ...

Setting up libmpfr4:amd64 (3.1.2-1) ...

Setting up libquadmath0:amd64 (4.8.2-19ubuntu1) ...

Setting up libtsan0:amd64 (4.8.2-19ubuntu1) ...

Setting up libyaml-0-2:amd64 (0.1.4-3ubuntu3) ...

Setting up libmpc3:amd64 (1.0.1-1ubuntu1) ...

Setting up openssl (1.0.1f-1ubuntu2.4) ...

Setting up ca-certificates (20130906ubuntu2) ...

debconf: unable to initialize frontend: Dialog

debconf: (TERM is not set, so the dialog frontend is not usable.)

debconf: falling back to frontend: Readline

debconf: unable to initialize frontend: Readline

debconf: (This frontend requires a controlling tty.)

debconf: falling back to frontend: Teletype

Setting up manpages (3.54-1ubuntu1) ...

Setting up binutils (2.24-5ubuntu3) ...

Setting up cpp-4.8 (4.8.2-19ubuntu1) ...

Setting up cpp (4:4.8.2-1ubuntu6) ...

Setting up libgcc-4.8-dev:amd64 (4.8.2-19ubuntu1) ...

Setting up gcc-4.8 (4.8.2-19ubuntu1) ...

Setting up gcc (4:4.8.2-1ubuntu6) ...

Setting up libc-dev-bin (2.19-0ubuntu6) ...

Setting up linux-libc-dev:amd64 (3.13.0-30.55) ...

Setting up libc6-dev:amd64 (2.19-0ubuntu6) ...

Setting up manpages-dev (3.54-1ubuntu1) ...

Setting up libruby1.9.1 (1.9.3.484-2ubuntu1) ...

Setting up ruby1.9.1-dev (1.9.3.484-2ubuntu1) ...

Setting up ruby-dev (1:1.9.3.4) ...

Setting up ruby (1:1.9.3.4) ...

Setting up ruby1.9.1 (1.9.3.484-2ubuntu1) ...

Processing triggers for libc-bin (2.19-0ubuntu6) ...

Processing triggers for ca-certificates (20130906ubuntu2) ...

Updating certificates in /etc/ssl/certs... 164 added, 0 removed; done.

Running hooks in /etc/ca-certificates/update.d....done.

 ---> c55c31703134

Removing intermediate container 3a2558904e9b

Step 4 : RUN gem install sinatra

 ---> Running in 6b81cb6313e5

unable to convert "\xC3" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to US-ASCII for README.rdoc, skipping

unable to convert "\xC3" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to US-ASCII for README.rdoc, skipping

Successfully installed rack-1.5.2

Successfully installed tilt-1.4.1

Successfully installed rack-protection-1.5.3

Successfully installed sinatra-1.4.5

4 gems installed

Installing ri documentation for rack-1.5.2...

Installing ri documentation for tilt-1.4.1...

Installing ri documentation for rack-protection-1.5.3...

Installing ri documentation for sinatra-1.4.5...

Installing RDoc documentation for rack-1.5.2...

Installing RDoc documentation for tilt-1.4.1...

Installing RDoc documentation for rack-protection-1.5.3...

Installing RDoc documentation for sinatra-1.4.5...

 ---> 97feabe5d2ed

Removing intermediate container 6b81cb6313e5

Successfully built 97feabe5d2ed

You’ve specified our docker build command and used the -t flag to identify our new image as belonging to the user ouruser, the repository name sinatra and given it the tag v2.


도커 파일의 위치를 명시하기 위해 .을 사용하였고, 이것은 현재 디렉토리를 의미한다.


작업시 빌드 프로세스를 보면 먼저 도커는 빌드 컨텍스트를 업로드 한다. 기본적으로 우리가 빌드하는 디렉토리의 컨텐츠이다. 여기서는 도커 데몬이 이미지의 실제 빌드를 수행하기 때문에 로컬 컨텍스트가 필요하다.


다음 도커파일의 각 지시들이 순서대로 수행되는 것을 알 수 있다. 그리고 모든 지시가 수행되면 97feabe5d2ed 이미지를 남기고 모든 중간 이미지를 지우는 것을 알 수 있다.


Note: 이미지는 127개 이상의 레이어를 가질 수 없다. 이 제약은 이미지의 전체 사이즈를 적정하게 유지하기 위해 글로벌하게 설정되었다.


이제 우리는 새로운 이미지로부터 컨테이너를 생성할 수 있다.

$ docker run -t -i ouruser/sinatra:v2 /bin/bash

root@8196968dac35:/#


Note: 이 가이드는 이미지를 생성하기 위한 간략한 소개이다. 자세한 내용은 Dockerfile Best Practices guide를 참조하자.


Setting tags on an image


우리는 또한 존재하는 이미지에 커밋 또한 빌드를 한 다음 태그를 추가할 수 있다. 이제 ouruser/sinatra에 새로운 태그를 추가해보자.

$ docker tag 5db5f8471261 ouruser/sinatra:devel


The docker tag command takes the ID of the image, here 5db5f8471261, and our user name, the repository name and the new tag.


이제 docker images 커맨드로 새로운 태그를 확인해보자.

$ docker images ouruser/sinatra

REPOSITORY          TAG     IMAGE ID      CREATED        SIZE

ouruser/sinatra     latest  5db5f8471261  11 hours ago   446.7 MB

ouruser/sinatra     devel   5db5f8471261  11 hours ago   446.7 MB

ouruser/sinatra     v2      5db5f8471261  11 hours ago   446.7 MB


Image Digests


이미지는 v2 또는 later 포맷을 이용하여 다이제스트라고 불리는 content-addressable 식별자를 가질 수 있다. 다이제스트 값을 출력하기 위해 --digest 플래그 를 명시하면 된다.


$ docker images --digests | head

REPOSITORY        TAG      DIGEST                                                                     IMAGE ID      CREATED       SIZE

ouruser/sinatra   latest   sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf    5db5f8471261  11 hours ago  446.7 MB


2.0 레지스트리에 다운로드 업로드 할때 push 또는 pull 커맨드는 이미지 다이제스트 값을 포함할 수 있다. 다이제스트값을 이용해 이미지를 다운로드할 수 있다.

$ docker pull ouruser/sinatra@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf


또한 다이제스틑 create, run, rmi 커맨드와도 같이 사용될 수 있고 도커파일에서 참조할 수도 있다.


Push an image to Docker Hub


새로운 이미지를 생성하였으면 docker push 명령으로 도커허브에 이미지를 업로들 할 수 있다.

$ docker push ouruser/sinatra

The push refers to a repository [ouruser/sinatra] (len: 1)


Sending image list


Pushing repository ouruser/sinatra (3 tags)

. . .


Remove an image from the host


docker rmi 명령으로 호스트의 이미지를 삭제할 수도 있다.

$ docker rmi training/sinatra

Untagged: training/sinatra:latest

Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d

Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f

Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0


Note: 이미지를 삭제하기 전에 이미지를 베이스로한 컨테이너가 존재하는지 먼저 확인하자.

반응형
반응형

Run a simple application


“Hello world in a container“에서 우리는 docker run 커맨트를 이용해 첫번째 컨테이너를 띄웠다. 우리는 foreground에서 대화형 컨테이너를 실행하였고, 또한 백그라운드에서 분리된 컨테이너를 실행하였다. 이러한 과정중에 몇가지 Docker 커맨드를 배울 수 있었다.


docker ps - 컨테이너들의 리스트를 출력

docker logs - 컨테이너의 표준 출력을 보여준다.

docker stop - 실행중인 컨테이너를 중지한다.


Learn about the Docker client


인지하지 못했지만 우리는 이미 도커 클라이언트를 이용하였다. 클라이언트는 단순한 커맨드라인이다. 클라리언트는 각 명령 과 각 명령의 일련의 플래그 및 인자를 처리한다.

# Usage:  [sudo] docker [subcommand] [flags] [arguments] ..

# Example:

$ docker run -i -t ubuntu /bin/bash


docker version 명령을 통해 우리는 버젼정보와 현재 설치된 도커 클라이언트와 데몬의 정보를 얻을 수 있다..

$ docker version


이 커맨드는 우리가 사용하고 있는 도커 클라이언트와 데몬의 버젼뿐만 아니라 Go의 버젼도 확인할 수 있다.

Client:

 Version:      1.8.2

 API version:  1.20

 Go version:   go1.4.2

 Git commit:   0a8c2e3

 Built:        Thu Sep 10 19:10:10 UTC 2015

 OS/Arch:      darwin/amd64


Server:

 Version:      1.8.2

 API version:  1.20

 Go version:   go1.4.2

 Git commit:   0a8c2e3

 Built:        Thu Sep 10 19:10:10 UTC 2015

 OS/Arch:      linux/amd64


Get Docker command help


도커 커맨드의 상세한 설명을 출력한다. 도움말은 옵션과 사용법을 상세히 설명한다. 사용가능한 커맨드의 리스트를 확인하려면 다음과 같은 커맨드를 사용한면된다.

$ docker --help


특정한 커맨드의 상세한 사용법이 궁금하다면 커맨드 다음에 --help 프래그를 명시하면 된다.


$ docker attach --help


Usage: docker attach [OPTIONS] CONTAINER


Attach to a running container


  --help=false        Print usage

  --no-stdin=false    Do not attach STDIN

  --sig-proxy=true    Proxy all received signals to the process


Running a web application in Docker


이제 도커 클라이언트에 관한 더 많은 내용에 대해서 배워보겠다. 더 많은 컨테이너를 실행할 것이다. 우리는 도커에 예제 웹어플리케이션을 실행해볼것이다.


우리는 Python Flask 어플리케이션을 실행할 것이다. 도커 커맨드는 다음과 같다.

$ docker run -d -P training/webapp python app.py


수행한 커맨드를 복습해보자. 우리는 두가지 플래그를 명시했다 : -d, -P. -d 플래그는 이미 본적이 있다. 이것은 컨테이너를 데몬으로 실행하겠다는 것이다. -P 플래그는 새로운 것인다. 호스트에게 컨테이너 내부의 필요한 네트워크 포트를 매핑하라고 도커에게 명령하는 것이다. 이것은 우리에게 웹 어플리케이션을 보여준다.


우리는 특정한 이미지를 명시했다. : traning/webapp. 이미지는 미리 빌드된 이미지로 간단한 Python Flask 웹 어플리케이션을 포함하고 있다.


마지막으로 우리는 컨테이너가 실행할 명령을 명시하였다. : python app.py. 이것은 우리의 웹 어플리케이션을 실행한다.


Viewing our web application container


이제 docker ps 명령을 통해 실행중인 컨테이너를 살펴보자.

$ docker ps -l

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES

b51ac2411ae0        training/webapp     "python app.py"     5 minutes ago       Up 5 minutes        0.0.0.0:32768->5000/tcp   desperate_franklin


우리는 새로운 플래그를 명시했는데 -l이다. 이것은 가장 마지막에 시작된 컨테이너의 상세를 리턴한다.


Note: 기본적으로 docker ps 커맨드는 실행중인 컨테이너에 대한 정보만을 보여준다. 만약 중지된 컨테이너에 대한 것을 확인할려면 -a 프래그를 명시해야한다.


우리는 처음으로 PORTS라는 중요한 칼럼이 상세에 추가된 것을 알 수 있다. 

PORTS

0.0.0.0:32768->5000/tcp


docker run 커맨드에 -P 플래그를 전달했을 때 이미지의 어떠한 포트가 호스트에 매핑되어 노출된 것을 알 수 있다.


Note: 도커 이미지의 포트가 어떻게 노출되는지는 이미지 빌드에 대해서 배울때 배우게 될 것이다.


이번 경우 도커 이미지의 5000 포트가 호스트의 32768 포트 노출된 것을 알 수 있다.


도커에서 네트워크 포트 바인딩은 설정할 수 있다. 지난 예제의 -P 플래그는 -p 5000의 숏컷이다. 우리는 또한 -p 플래그를 통해 특정 포트를 바인딩할 수도 있다.

$ docker run -d -p 80:5000 training/webapp python app.py


이것은 컨테이너 내부의 5000포트를 우리 로컬 호스트의 80 포트로 매핑하는것이다. 하나 궁금중이 생길수 있다. 왜 1:1 포트 매핑을 해야 하는가?


두가지 파이썬 어플리케이션을 테스트한다고 가정해보자 컨테이너 내부에서는 둘다 5000 포트로 바인딩되어 있을 것이다. 도커 매핑이 없다면 우리의 호스트에 하나의 컨테이너 밖에 띄울 수 없는 상황이 된다.


이제 브라우저에서 32768포트로 접근해보자.


Viewing the web application.


파이썬 어플리케이션이 수행중이다.


Note: 만약 OS X, Windows, Linux에서 버츄얼 머신을 사용하고 있다면 localhost 대신에 버츄얼 호스트의 IP를 사용해야 한다. 이럴 경우 docker-machine ip your_vm_nam 커맨드로 IP를 얻을 수 있다. 


$ docker-machine ip default

192.168.99.100


이 경우 브라우저에서 http://192.168.99.100:32768로 접속해야 한다. 


A network port shortcut


docker ps 명령으로 매핑된 포트를 보는 것은 약간 별로이다. 이럴때 사용할 수 있는 숏컷이 docker port이다. docker port에 컨테이너의 id나 이름을 명시하면 퍼블릭으로 노출된 port을 얻을 수 있다.

$ docker port desperate_franklin 5000

0.0.0.0:32768



Viewing the web application’s logs


또한 우리는 웹 어플리케이션의 로그를 볼 수 있는데 이것은 이전의 예와 동일하다.


$ docker logs -f desperate_franklin

 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

192.168.99.1 - - [11/Mar/2016 06:16:03] "GET / HTTP/1.1" 200 -

192.168.99.1 - - [11/Mar/2016 06:16:03] "GET /favicon.ico HTTP/1.1" 404 -


이번에는 새로운 플래그 -f를 볼 수 있다. 이것은 마치 tail -f 커맨드와 비슷하게 동작한다.


Looking at our web application container’s processes


우리는 또한 docker top 커맨드로 컨테이너 내부에 실행되는 프로세스를 확인할 수 있다.

$ docker top desperate_franklin

PID                 USER                COMMAND

1435                root                python app.py



Inspecting our web application container


마지막으로 docker inspect 명령으로 도커의 로우-레벨정보를 획득할 수 있다. 이것은 특정 컨테이너의 유용한 설정정보와 상태정보를 JSON 도큐먼트로 리턴한다.

$ docker inspect desperate_franklin

[

{

    "Id": "b51ac2411ae0923b4b968ab034209a7e3be63a3214d2a9ef94b21002300902df",

    "Created": "2016-03-11T05:48:30.151535507Z",

    "Path": "python",

    "Args": [

        "app.py"

    ],

. . .


우리는 또한 특정한 엘리먼트에 대한 요청으로 정보를 축약해서 얻을 수도 있다. 다음 예제는 컨테이너의 IP 주소에 대한 정보를 얻는 예제이다. we would:

$ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' desperate_franklin

172.17.0.5


Stopping our web application container


이제 웹어플리케이션이 동작하는 것을 확인하였다. 이제 중지 시켜보자. docker stop 커맨드에 컨테이너의 이름을 인자로 전달하면 된다.

$ docker stop desperate_franklin

desperate_franklin


docker ps 명령으로 컨테이너가 종료된 것을 확인하자.

$ docker ps -l


Restarting our web application container


컨테이너를 다시 기동하는데는 두가지 초이스가 있다. : 새로운 컨테이너를 만들거나 예전것을 리스타트하거나. 먼저 이전 컨테이너를 다시 시작해보자.

$ docker start desperate_franklin

desperate_franklin


docker ps 명령으로 확인하고 브라우저를 통해 접속해보자.


Note: docker restart 커맨드로도 가능하다. restart 커맨드는 컨테이너를 stop하고 다시 start한다.


Removing our web application container


마지막으로 컨테이너를 삭제해보자.


$ docker rm desperate_franklin

Error response from daemon: Cannot destroy container desperate_franklin: Conflict, You cannot remove a running container. Stop the container before attempting removal or use -f

Error: failed to remove containers: [desperate_franklin]


위에서 보다시피 삭제하기 전에는 먼저 중지를 수행해야 한다.


$ docker stop desperate_franklin

desperate_franklin

$ docker rm desperate_franklin

desperate_franklin


이제 컨테이너는 중지되고 삭제되었다.


반응형

'Programming > Docker' 카테고리의 다른 글

Docker - Build your own images  (0) 2016.03.11
Docker Engine - Hello world in a container  (2) 2016.02.18
Docker Engine - Architecture  (0) 2016.02.17
Docker Engine - Quickstart Containers  (1) 2016.02.17
Docker - Tag, push, and pull your image  (0) 2016.02.02
반응형

Hello world in a container


그래서 도커의 모든것은 무엇인가?


도커는 컨테이너내에서 어플리케이션을 실행하고 세상을 만들 수 있게 한다. 컨테이너내의 어플리케이션을 실행하는 명령은 다음과 같다.


docker run


Note: 도커 시스템 설정에 따라 도커 명령에 sudo을 항당 붙어야 할 수 있다. 이러한 것을 피하기 위해 docker라는 유닉스 유저그룹을 생성하고 거기에 유저를 추가하자.


Run a Hello world


그냥 따라해보자.


$ docker run ubuntu /bin/echo 'Hello world'

Hello world


첫번째 컨테이너 구동에 성공했다.


어떤일들이 일어났는지 살펴보자.


먼저 도커 바이너리를 명시하고 실행하고하는 명령을 명시한다. docker run의 조합은 컨테이너를 실행시키는 것이다.


다음 이미지를 명시하자 : ubuntu. 이것은 컨테이너의 소스이다. 도커는 이것을 이미지라고 부른다. 이 경우 우분투 OS를 사용한다.


먼저 도커는 해당이미지가 호스트에 있는지 찾는다. 만약에 존재하지 않는다면 퍼블릭 이미지 레지스트리 도커허브로부터 이미지를 다운받는다.


그런 다음 컨테이너 내부에서 다음과 같은 커맨드를 실행한다.


/bin/echo 'Hello world'


우리는 커맨드라인에 다음과 같은 결과를 볼 수 있다.


Hello world


그런 다음 컨테이너는 어떻게 될까? 도커 컨테이너는 명령을 수행할때만 활성화된다. 여기서는 Hello world를 출력한 다음 컨테이너는 중지된다.


An interactive container


docker run 커맨드를 다시 수행하는데 이번에는 아래와 같이 수행해보자.


$ docker run -t -i ubuntu /bin/bash

root@af8bae53bdd3:/#


여기서 우리는 다시 우분투 이미지를 구동하였다. 그리고 또한 우리는 -t 와 -i라는 두가지 플래그를 함께 전달하였다. -t 플래그는 컨테이너 내부에 pseudo-tty를 할당하는 것이고, -i는 컨테이넌 표준 입력에 대한 대화형 연결을 생성하는 것이다.


또한 우리는 새로운 커맨드를 명시하였다. : bin/bash. 이것은 컨테이너 내부에 배쉬셀을 구동할 것이다. 


이제 컨테이너 내부의 다음과 같은 명령들을 수행해보자.


root@af8bae53bdd3:/# pwd

/

root@af8bae53bdd3:/# ls

bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var


pwd를 실행하면 / 루트 디렉토리가 표시하는 것을 알 수 있고, ls 명령을 통해 루트 디렉토리의 하위 디렉토리들이 나타나는 것을 알 수 있다.


exit 커맨드 또는 Ctrl-D로 배쉬 셀에서 빠져나올 수 있다.

root@af8bae53bdd3:/# exit


배쉬셀 프로세스가 종료되었으므로 컨테이너는 중지된다.


A daemonized Hello world


명령을 실행하고 바로 종료되는 것은 일반적으로 유용하지 못하다. 이제 컨테이너를 데몬으로 실행해보자. 도커에서 대부분의 컨테이너들은 데몬 형태로 실행될 것이다.


다시 다음과 같은 명령을 수행해보자.


$ docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

d80bcaf03897ac48647ac78104607af1edca9f81795b55d171d09a179697b9d5


우리의 hello world 출력은 어디에 갔을까? 우리는 도커를 -d라는 플래그를 명시하여 구동하였다. -d 플래그는 도커를 백그라운드 데몬으로 실행하라는 명령이다.


우리는 또한 똑같은 이미지를 명시하였다. : ubuntu.


마지막으로 우리는 다음과 같은 커맨드를 실행하였다.

/bin/sh -c "while true; do echo hello world; sleep 1; done"


이것은 멍청한 데몬이다. 쉘스크립트는 무한대로 hello world를 출력할 것이다.


그러면 hello world는 왜 볼 수 없다? 우리는 대신에 긴 문자열을 리턴받았다.

d80bcaf03897ac48647ac78104607af1edca9f81795b55d171d09a179697b9d5


이것이 컨테이너 아이디이다.


Note: 컨테이너 아이디는 길고 어렵다. 다음에 짧은 아이디나 컨테이너에 이름을 쉽게 부여하는 방법을 배울 것이다.


이 컨테이너 아이디를 이용하여 hello world 데몬에 어떤일이 벌어지는지 알 수 있다.


먼저 컨테이너가 실행중이라는 것을 알아보자. docker ps 라는 명령을 수행하면 된다. docker ps는 도커 데몬에 대한 정보를 질의하는 명령이다.


$ docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES

d80bcaf03897        ubuntu              "/bin/sh -c 'while tr"   6 minutes ago       Up 6 minutes                            high_jang


우리는 데몬 컨테이너를 확인할 수 있다. doekcer ps는 몇가지 유용한 정보를 포함하고 있는데 첫번째 내용이 컨테이너 아이디이다.


또한 우리는 컨테이너를 빌드하기 위해 사용한 이미지가 우분투임을 알 수 있고 실행시 수행된 명령 자동으로 할당된 이름등을 확인할 수 있다.


Note: 컨테이너가 시작되면 도커는 이름을 자동으로 생성한다. 하지만 이후에 직접 지정할 수 있는 방법을 배울 것이다.


컨테이너가 동작하고 있다는 것을 알 수 있다. 그러면 무엇을 하고 있는지 물어보자. docker logs 커맨드를 수행해보자. 이때 컨테이너 이름을 같이 명시해주자.


$ docker logs high_jang

hello world

hello world

hello world

hello world

hello world


docker logs 커맨드는 도커내부의 표준출력이 리턴된다.


우리는 데몬은 동작하고 있고 이것이 우리의 첫번째 도커라이즈드 어플리케이션이다.


이제 docker stop 커맨드로 컨테이너를 중지해보자.


$ docker stop high_jang

high_jang


docker stop명령은 우아하게 수행중인 컨테이너를 중지한다. 성공적으로 중지되면 컨테이너의 이름이 반환된다.


docker ps 명령으로 컨테이너가 수행중인지 알아보자.


$ docker ps

CONTAINER ID  IMAGE         COMMAND               CREATED        STATUS       PORTS NAMES


완벽하다. 우리의 컨테이너는 중지되었다.

반응형

'Programming > Docker' 카테고리의 다른 글

Docker - Build your own images  (0) 2016.03.11
Docker - Run a simple application  (1) 2016.03.11
Docker Engine - Architecture  (0) 2016.02.17
Docker Engine - Quickstart Containers  (1) 2016.02.17
Docker - Tag, push, and pull your image  (0) 2016.02.02
반응형

Understand the architecture


도커란 무엇인가?


도커는 개발하고 적재하고 어플리케이션을 실행하기 위한 오픈 플랫폼이다. 도커는 어플리케이션을 더빨리 딜리버리하기 위해서 설계되었다. 도커와 함께라면 인프라스트럭처와 어플리케이션을 분리 할 수 있으며, 인프라스트럭처를 어플리케이션처럼 관리할 수 있다. 도커는 코드를 더 빨리 적재하고, 더 빨리 테스트하고, 더 빨리 디플로이하고 코드를 작성하고 코드를 실행하는 사이클을 더 짧게 만들어준다.


도커는 이러한 일들을 결합된 커널 컨테이너 기술로 제공한다. 이러한 워크플로우와 툴들은 당신의 어플리케이션을 디플로이하고 관리하는 것을 도와준다.


핵심적으로 도커는 컨테이너에 안전하고 독립적으로 거의 모든 어플리케이션을 실행하는 방법을 제공한다. 독립과 안정성은 당신의 호스트에 많은 컨테이너를 실행하는 것을 허용한다. 컨테이너의 경량화에 의해 하이퍼바이저의 추가적인 부하없이 실행할 수 있으며, 이것은 하드웨어에 더많은 부분을 활용할 수 있다는 것이다.


컨테이너 환경은 다음과 같은 경우에 툴과 플랫폼으로써 도움을 준다.


어플리케이션은 도커 컨테이너로 넣는다.

컨테이너를 배포하고 적재함으로써 개발과 테스트를 용이하게 한다.

어플리케이션을 프로덕션 환경에 배포한다. 로컬 데이터 센터든 클라우드든 상관없다.


What can I use Docker for?


더빨리 어플리케이션을 배포한다.


도커는 개발 라이프사이클을 완벽하게 지원한다. 도커는 어플리케이션과 서비스를 로컬컨테이너상에서 개발할 수 있도록 해준다. 이것은 CI나 배포 워크플로우와 통합될 수 있다.


예를 들어 개발자는 로컬에 코드를 작성하고 그것을 도커를 통해 동료의 개발 스택에 공유할 수 있다. 준비가 되면 그들의 코드를 푸쉬하고 그것을 테스트 환경에 보내고 필요한 테스트를 수행할 수 있다. 테스트 환경으로 부터 도커 이미지를 푸쉬하여 프로덕션에 당신의 코드를 배포할 수 있다.


더 쉽게 디플로이하고 스케일링할 수 있다. 


도커의 컨테이너 베이스 플랫폼은 대량의 워크로드에 더욱 적합하다. 도커 컨테이너는 개발자의 로컬 호스트에서 실행될 수 있다. 또한 물리장비 또는 vm이든 데이터센터든 클라우드든 상관없이 실행할 수 있다.


도커의 이식성과 경량성은 쉽고 다이나믹하게 워크로드를 관리할 수 있게 해준다. 도커를 사용하면 어플리케이션과 서비스를 쉽게 스케일업 또는 티어다운할 수 있다. 도커의 속도는 거의 실시간에 가깝게 스케일링을 할 수 있다.


더 밀도있고 더 많은 워크로드 수행


도커는 가볍과 빠르다. 하이퍼바이저 기반 vm에 viable 그리고 cost-effective 한 대안으로 제공한다. 도커는 특히 고집적 환경에 더 유용하다. 예를 들어 당신만의 클라우드 혹은 PAAS를 구성할 수 있다. 그러나 또한 작거나 중간 사이브의 디플로이환경에도 유용하며 자원을 더욱 효율적으로 사용할 수 있도록 만들어 줄것이다.


What are the major Docker components?


도커는 두개의 주요 컴포넌트를 가지고 있다.


Docker: 오픈소스 컨테이너 플랫폼

Docker Hub:  도커 컨테이너를 관리하고 공유하기 위한 SAAS

Note: 도커의 라이센스는 Apache 2.0이다.


What is Docker’s architecture?


도커는 클라이언트-서버 아키텍처를 이용한다. 도커 클라이언트는 도커 데몬과 대화한다. 도커 데몬은 도커 컨테이너를 빌드, 실행, 분산을 담당한다. 도커 클라이언트와 데몬은 같은 시스템에서 실행되거나 도커 클라이언트가 리모트에 있는 도커 데몬에 접속할 수 있다. 도커 클라이언트와 데몬은 소켓이나 RESTful API를 통해서 통신한다.


The Docker daemon


위의 다이어그램에서 보다시피 도커 데몬은 호스트 모신에서 실행된다. 유저는 도커 데몬과 직접 통신하는 대신 도커 클라이언트를 통해서 통신한다.


The Docker client


도커 클라이언트는 도커와 통신하는 프라이머리 유저이다. 유저로부터 명령을 받아서 도커 데몬으로 전송하고 결과를 받는다.


Inside Docker


도커의 내부구조를 이해하기 위해서는 3가지 컴포넌트에 대해서 알 필요가 있다.


Docker images.

Docker registries.

Docker containers.


Docker images


도커 이미지는 읽기전용 템플릿이다. 예를들어 이미지는 우분투 OS와 아파치 그리고 설치된 웹어플리케이션을 포함할 수 있다. 이미지는 도커 컨테이너를 생성하기 위해서 사용된다. 도커는 새로운 이미지를 생성하고 기존 이미지를 업데이트하는 단순한 방법을 제공한다. 또한 다른 사람이 이미 생성한 도커 이미지를 다운로드 받을 수도 있다. 도커 이미지는 도커의 빌드 컴포넌트이다.


Docker registries


도커 레지스트리는 이미지를 저장한다. 이것은 퍼블릭 또는 프라이빗 스토어로부터 이미지를 업로드 또는 다운로드 할 수 있다. 퍼블릭 도커 레지스트리는 도커 허브에 의해 제공된다. 도커 허브는 당신이 사용할 수 있는 대량의 이미지 컬렉션을 제공한다. 도커 레지스트리는 도커의 분산 컴포넌트이다.


Docker containers


도커 컨테이너는 디렉토리와 비슷하다. 도커 컨테이너는 어플리케이션을 실행하는 모든것을 포함하고 있다. 도커 이미지로부터 각 컨테이너는 생성된다. 도커 컨테이너는 실행하고, 시작되고, 중지되고, 이동되고, 삭제될 수 있다. 각 컨테이너는 어플리케이션 플랫폼에 완전하게 독립적이다. 도커 컨테이너는 도커의 실행 컴포넌트이다.


So how does Docker work?


어플리케이션을 저장하기 위해 도커 이미지를 생성할 수 있다.

도커 이미지로부터 어플리케이션을 실행하기 위해 도커 컨테이너를 생성할 수 있다.

도커허브나 자신만의 레지스트리를 통해 도커 이미지를 공유할 수 있다.


이제 이러한 엘리먼트들이 어떻게 함께 결합되는지 살펴보자.


How does a Docker image work?


우리는 이미 도커 이미지는 읽기 전용 템플릿이라는 것을 알고 있다. 이것은 도커 컨테이너를 실행하기 위해 사용된다. 각 이미지는 일련의 레이어로 구성된다. 도커는 이러한 레이어를 하나의 이미지로 결합하기 위해 union 파일시스템을 이용한다. 유니온 파일 시스템은 분리된 파일 시스템을 파일과 디렉토리를 하나의 파일 시스템으로 구성한다. 


도커가 경량화된 하나의 이유는 이러한 레이어에 때문이다. 도커 이미지를 변경하면 - 예를들어 어플리케이션을 새로운 버젼으로 업데이트하면 - 새로운 레이어가 생성된다. 그러므로 전체 이미지를 대체하거나 전체를 리빌딩하기 않고 단지 레이어를 추가하거나 변경한다. 이제 새로운 이미지 전체를 분산할 필요없이 단지 업데이트하므로 도커 이미지 분산은 더 빠르고 단순해진다.


모든 이미지는 기본 이미지로부터 시작한다. 예를 들어 우분투는 기본 우분트 이미지로부터 페도라는 기본 페도라이미지로 부터 시작한다. 또한 새로운 이미지를 위해 당신의 이미지를 베이스로 시작할 수도 있다. 예를들어 기본 아파치 이미지를 가지고 있다면 그것을 기반으로 웹어플리케이션 이미지를 생성할 수 잇을 것이다.


Note: 도커는 일반적으로 도커허브로부터 기본 이미지를 제공받는다.


도커 이미지는 이러한 기본 이미지를 기반으로 빌드된다. 빌드시에 단순하고 직관적인 일련의 스텝을 지시할 수 있다. 이러한 지시에 따라 이미지에 새로운 레이어를 생성할 수 있다. 지시는 다음과 같은 액션을 포함할 수 있다.


커맨드를 실행한다. 

파일이나 디렉토리를 추가한다.

환경변수를 생성한다.

이미지로부터 컨테이너가 구동될때 실행할 프로세스를 지정한다.


이러한 지시는 Dockerfile이라고 불리는 파일에 저장된다. 도커는 이미지 빌드 요청시 Dockerfile을 읽고 지시를 수행한 다음, 최종적으로 이미지를 리턴한다.


How does a Docker registry work?


도커 레지스트리는 도커 이미지를 저장하기 위한 스토어이다. 도커허브와 같은 퍼블릭 레지스트리에 도커 이미지를 푸쉬할 수 있고 또한 방화벽 내의 프라이빗 레지스트리를 운영할 수도 있다.


도커 클라이언트를 사용하여 이미 배포된 이미지를 찾을수 있고 그러한 이미지들을 호스트로 풀해서 컨테이너를 생성하는데 사용할 수도 있다.


도커 허브는 이미지를 위한 퍼블릭 그리고 프라이빗 레지스트리를 제공한다. 퍼블릭 스토리지는 누구나에게나 조회하고 다운로드받을 수 있다. 프라이빗 스토리지는 허용된 사용자에게만 검색과 다운로드가 가능하다. 


How does a container work?


컨테이너는 OS, 유저추가파일 및 메타데이터로 구성된다. 각 컨테이너는 이미지로부터 빌드된다. 이미지는 어떠한 컨테이너가 포함되어 있는지 컨테이너가 실행될 때  어떠한 프로세스가 실행되는지 그리고 다양한 설정 데이터들을 포함한다. 도커 이미지는 읽기전용이다. 이미지로부터 도커가 컨테이너를 실행할때 이미지와 최상단에 읽기-쓰기가 가능한 레이어가 추가된다.


What happens when you run a container?


도커 바이너리나 API를 통해 도커 클라이언트는 도커 데몬에게 컨테이너를 실행하라고 요청할 수 있다.


$ docker run -i -t ubuntu /bin/bash


이 커맨드를 분석해보자. 도커 바이너리를 사용한 도커 클라이언트가 구동된다. run 옵션은 새로운 컨테이너를 구동하라는 명령이다. 


도커를 실행할려면 최소한 다음과 같은 내용이 기술되어야 한다.


어떠한 도커 이미지로부터 컨테이너를 빌드할 것인가? 여기에서는 우분투 즉 기본 우분투이다.

명령은 컨테이너가 실행되었을 때 실행할 커맨드를 포함할 수 있다. 여기서는 /bin/bash 이다. 이 명령은 새로운 컨테이너내의 배쉬쉘을 실행시킨다.


이 명령이 실행되면 내부적으로 어떠한 일들이 발생할까?


도커는 다음과 같은 일들을 수행한다.


도커 이미지를 풀한다 : 도커는 우분투 이미지가 존재하는지 확인한다. 만약 호스트에 없다면 도커는 도커 허브로부터 다운로드 한다. 만약 존재한다면 도커는 해당 이미지를 재사용한다.

새로운 컨테이너 생성: 도커가 이미지를 가지고 있다면 해당 이미지를 이용하여 새로운 컨테이너를 생성한다.

파일 시스템을 할당하고 읽기-쓰기 레이어를 마운트 : 파일 시스템에 새로운 컨테이너를 생성하고 이미지에 읽기-쓰기 레이어를 추가한다.

네트워크/브리지 인터페이스 할당 : 로컬 호스트와 통신할 수 있는 네트워크 인터페이스를 도커 컨테이너에 할당

셋업 IP 어드레스 : 주소풀로부터 이용가능한 IP주소를 찾아서 할당함

명시한 프로세스 실행 : 어플리케이션 실행

어플리케이션 출력 결과 캡쳐 및 제공 : 표준입출력 및 에러출력에 연결하여 어플리케이션이 어떻게 실행되고 있는지 제공


이제 수행중인 컨테이너를 가지게 되었다. 


The underlying technology


도커는 Go로 작성되었고 기능을 제공하기 위해 몇몇의 커널 기능을 이용한다.


Namespaces


도커는 네임스페이스 기술을 이용하여 독립된 워크스페이스를 제공한다. 컨테이너가 실행되면 도커는 컨테이너의 일련의 네임스페이스를 생성한다.


이것은 독립적인 레이어를 제공한다. 각 컨테이너는 자신만의 네임스페이스내에서 실행되고 그것의 외부로 접근하지 않는다.


도커가 리눅스에서 사용하는 네임스페이스는 다음과 같다.


The pid namespace: 프로세스 독립을 위해 사용된다. (PID: Process ID).

The net namespace: 네트워크 인터페이스 관리를 위해서 사용된다. (NET: Networking).

The ipc namespace: IPC 리소스 제어 관리를 위해서 사용된다. (IPC: InterProcess Communication).

The mnt namespace: 마운트 포인트 관리를 위해서 사용된다. (MNT: Mount).

The uts namespace: 커널과 버젼 식별자 관리를 위해서 사용된다. (UTS: Unix Timesharing System).


Control groups


리눅스에서 도커는 cgroups라고 하는 또다른 기술을 이용한다. 독립된 환경에서 실행되는 어플리케이션은 주요한 점은 당신이 원하는 자원만을 사용해야 한다는 것이다. 컨테이너가 호스트의 멀티테넌스라는 것을 확실히 한다. 컨트롤 그룹은 도커에 컨테이너가 공유할 수 있는 하드웨어 리소스를 허락하고 원한다면 제약과 한계를 세팅할 수 있다. 예를 들어 특정한 컨테이너에 메모리르 사용량을 제약할 수 있다.


Union file systems


UFS는 레이어 생성에 의해 조작되는 파일 시스템이다. 도커는 UFS를 이용해서 컨테이너를 위한 빌딩블록을 제공한다. 도커는 몇가지 UFS를 이용할 수 있다. : AUFS, btrfs, vfs, DeviceMapper.


Container format


도커는 컨테이너 포맷이라고 불리는 컴포넌트들을 조합한다. 기본 컨테이너 포맷은 libcontainer인데, 미래에는 다른 컨테이너 포맷을 지원할 수도 있다. 예를 들어 BSD Jails 또는 Solaris Zones이 있다.

반응형
반응형

Quickstart Docker Engine


이 퀵스타트는 도커 엔진이 동작하도록 설치가 되어있다고 가정한다. 엔진이 설치되었는지를 확인하기 위해 다음과 같은 명령을 수행해보자.


$ docker info

Containers: 12

Images: 14

Storage Driver: aufs

 Root Dir: /mnt/sda1/var/lib/docker/aufs

 Backing Filesystem: extfs

 Dirs: 38

 Dirperm1 Supported: true

Execution Driver: native-0.2

Logging Driver: json-file

Kernel Version: 4.0.9-boot2docker

Operating System: Boot2Docker 1.8.2 (TCL 6.4); master : aba6192 - Thu Sep 10 20:58:17 UTC 2015

CPUs: 1

Total Memory: 1.956 GiB

Name: default

ID: HKZF:4Z5M:L7XJ:ISX7:HEVF:BDZS:EBWI:LOR3:KVS4:JNRI:UDSA:V4SH

Debug mode (server): true

File Descriptors: 12

Goroutines: 16

System Time: 2016-02-17T01:28:02.039605398Z

EventsListeners: 0

Init SHA1:

Init Path: /usr/local/bin/docker

Docker Root Dir: /mnt/sda1/var/lib/docker

Username: devsun98

Registry: https://index.docker.io/v1/

Labels:

 provider=virtualbox


만약 도커를 설치했는데, 명령을 찾을 수 없다거나 /var/lib/docker/repositories에 대한 권한이 없다고 나온다면 불완전하게 도커 엔진이 설치되었거나 엔진에 접근할 수 있는 권한이 불충분하다는 것이다. 도커 엔진에 대한 명령은 도커 그룹이나 루트 유저로 실행해야 한다.


엔진 시스템 설정에 따라 각 도커 명렬은 sudo로 수핼시켜야 할 수 있다. sudo를 회피하는 하나의 방법은 docker라는 유닉스 그룹을 생성하고 전체 도커 커맨드에 접근할 수 있는 유저를 docker 그룹에 추가하는 것이다.


도커 엔진의 설치나 sudo 설정에 대한 더 많은 정보를 얻으려면 당신의 os에 설치 지시에 언급된 내용을 잘 살펴보자.


Download a pre-built image


$ docker pull ubuntu

Using default tag: latest

latest: Pulling from library/ubuntu

f15ce52fc004: Pull complete

c4fae638e7ce: Pull complete

a4c5be5b6e59: Pull complete

8693db7e8a00: Pull complete

library/ubuntu:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.

Digest: sha256:457b05828bdb5dcc044d93d042863fba3f2158ae249a6db5ae3934307c757c54

Status: Downloaded newer image for ubuntu:latest


이 명령은 도커허브에서 ubuntu라는 이미지를 찾은 후 로컬 이미지 캐쉬로 해당 이미지를 다운로드 받는 것이다.


Running an interactive shell


우분투 이미지에 있는 대화형 쉘을 실행해보자.


$ docker run -i -t ubuntu /bin/bash

root@5615e8b6c789:/#


-i 플래그는 대화형 컨테이너를 실행하는 것이다. -t 플래그는 표준입출력을 위한 pseudo-TTY를 생성한다.


exit 명령을 사용하지 않고 tty를 분리한다면 Ctrl-p + Ctrl-q 이스케이브를 사용하면 된다. 컨테이너를 exit로 나오면 stopped 상태로 컨테이너는 계속 존재할 것이다. stopped 나 running 상태의 모든 컨테이너를 리스트할려면 docker ps -a 커맨드를 사용하면 된다.


To detach the tty without exiting the shell, use the escape sequence Ctrl-p + Ctrl-q. The container will continue to exist in a stopped state once exited. To list all containers, stopped and running, use the docker ps -a command.


Bind Docker to another host/port or a Unix socket


주의 : 기본 도커 데몬에 바인딩된 TCP 포트 또는 유닉스 docker 유저 그룹을 변경시키면 non-root 유저가 호스트에 대한 root 권한을 획득할 수 있는 보안 리스크가 증대된다. docker에 접근 권한을 확실히 해야한다. 만약 TCP port를 바인딩하면 누구든지 해당 포트로 모든 도커에 접근할 수 있다. 


-H 플래그로 도커 데몬이 특정한 IP나 포트를 listen할 수 있도록 만들 수 있다. 기본적으로 도커 데몬은 unix:///var/run/docker.sock에 있는 내용들을 루트 유저에 의한 로컬 커넥션만을 허용한다. 0.0.0.0:2375 또는 특정한 호스트 IP로 세팅하면 모두에게 접근권한을 주는 것이다. 하지만 이것은 권장하지 않는데 이유는 데몬이 실행되고 있는 호스트에 루트 권한을 획득할 수 있는 위험이 있기 때문이다.


비슷하게 도커 클라이언트는 -H를 사용하여 커스텀 포트로 접속할 수 있다. 도커 클라이언트는 기본적으로 unix:///var/run/docker.sock를 리눅스에서는 사용하고 윈도우에서는 tcp://127.0.0.1:2376을 사용한다.


-H는 접근 호스트와 포트를 할당한다. 


tcp://[host]:[port][path] or unix://path


For example:


tcp:// -> TCP 접속 로컬호스트에서 2376 포트로 TLS 암호화가 설정된 상태로 가능 또는 2375 포트로 plain text 커뮤니케이션 가능

tcp://host:2375 -> host:2375 상에 TCP 접속

tcp://host:2375/path -> host:2375으로 TCP 접속하고 모든 리퀘스트에 path를 첨가

unix://path/to/socket -> path/to/socket에 위치한 Unix 소켓


-H 하고 비워두면 -H를 전달하지 않았을때와 같음


-H 플래그는 TCP 바인딩을 위한 단순한 폼을 허용함 


`host:` 또는 `host:port` 또는 `:port`


도커를 데몬모드로 실행 


$ sudo <path to>/docker daemon -H 0.0.0.0:5555 &


우분투 이미지를 다운로드


$ docker -H :5555 pull ubuntu


또한 우리는 다수의 -H를 사용할 수 있다. 예를들어 tcp와 유닉스 소켓을 모두 리슨하고 싶다면 다음과 같이 한다.


도커를 데몬 모드로 실행


$ sudo <path to>/docker daemon -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock &


디폴트 유닉스 소켓을 이용하여 우분투 이미지를 다운로드


$ docker pull ubuntu


또는 TCP 포트를 사용해서 다운로드


$ docker -H tcp://127.0.0.1:2375 pull ubuntu


Starting a long-running worker process


long-running 프로세스는 매우 유용하다.

$ JOB=$(docker run -d ubuntu /bin/sh -c "while true; do echo Hello world; sleep 1; done")


작업의 아웃풋을 수집하자.

$ docker logs $JOB


작업을 종료하자.

$ docker kill $JOB


Listing containers


$ docker ps # running 중인 컨테이너 리스트

$ docker ps -a # 모든 컨테이너 리스트


Controlling containers


# 새로운 컨테이너 시작

$ JOB=$(docker run -d ubuntu /bin/sh -c "while true; do echo Hello world; sleep 1; done")


# 컨테이너 종료

$ docker stop $JOB


# 컨테이너 시작

$ docker start $JOB


# 컨테이너 재시작

$ docker restart $JOB


# 컨테이너 킬

$ docker kill $JOB


# 컨테이너 제거

$ docker stop $JOB # 제거할 컨테이너는 반드시 종료되어야 한다.

$ docker rm $JOB


Bind a service on a TCP port


# 컨테이너의 4444 포트를 바인드 시켜 netcat이 해당 포트를 리슨하게 한다.

$ JOB=$(docker run -d -p 4444 ubuntu:12.10 /bin/nc -l 4444)


# 컨테이너의 Nated 퍼블릭 포트는 무엇인가?

$ PORT=$(docker port $JOB 4444 | awk -F: '{ print $2 }')


# 퍼블릭 포트로 연결한다.

$ echo hello world | nc 127.0.0.1 $PORT


# 네트워크 연결이 잘 동작하는것을 확인한다.

$ echo "Daemon received: $(docker logs $JOB)"


Committing (saving) a container state


컨테이너 상태를 이미지에 저장한다. 상태는 재사용될 수 있다.


컨테이너를 커밋하면 도커는 소스 이미지와 현재 상태의 이미지와 차이점만을 저장한다. 가지고 있는 이미지를 출력하기 위해서는 docker images 명령을 사용한다.


# 새로운 이름을 가진 이미지로 컨테이너를 커밋한다.

$ docker commit <container> <some_name>


# 이미지를 리스트한다.

$ docker images



반응형
반응형

이번 섹션에서는 우리가 생성한 리파지토리에 docker-whale 이미지를 태그하고 푸쉬 해보겠다. 이것이 끝나면 우리는 리파지토리로 부터 새로운 이미지를 풀해보겠다.


Step 1: Tag and push the image


아직 터미널을 열지 않았다면 터미널을 열어라.


터미널이 오픈되면 당신이 현재 가지고 있는 도커 이미지를 확인해보자. docker images라고 명령을 수행해보자.


$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

hello-world         latest              af340544ed62        5 months ago        960 B

docker/whalesay     latest              fb434121fc77        8 months ago        247 MB


docker-whalesay 이미지의 아이디를 확인해보자.


이 예제에서 아이디는  fb434121fc77.


여기서 주의할 점은 REPOSITORY는 repository를 보여준다. 하지만 docker-whalesay의 네임 스페이스는 아니다. 우리는 도커 허브를 위한 네임스페이스를 포함할 필요가 있는데 이때는 계정과 네임스페이스를 연관지어야 한다. 일단 네임스페이스는 당신의 계정명과 같다.


이미지 아이디를 이용해서 도커  tag 명령과 함께 docker-whale이미지를 태그해보자.


커맨드는 다음과 같이 구성된다.


물론 계정과 이미지 아이디는 당신의 것을 입력해야 한다.


toddsonui-MacBook-Pro:~ devsun$ docker tag fb434121fc77 devsun98/whalesay:latest

toddsonui-MacBook-Pro:~ devsun$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

hello-world         latest              af340544ed62        5 months ago        960 B

docker/whalesay     latest              fb434121fc77        8 months ago        247 MB

devsun98/whalesay   latest              fb434121fc77        8 months ago        247 MB


도커 login 명령을 이용해서 도커 허브에  로그인을 수행하자.

로그인 명령은 다음과 같다. 패스워드를 정확하게 입력하여 로그인에 성공하면 다음과 같은 메시지가 나온다.

$ docker login --username=devsun98 --email=devsun98@gmail.com

Password:

WARNING: login credentials saved in /Users/devsun/.docker/config.json

Login Succeeded


도커 push 명령을 이용해서 도커허브에 푸쉬해보자.

$ docker push devsun98/whalesay

The push refers to a repository [docker.io/devsun98/whalesay] (len: 1)

fb434121fc77: Image successfully pushed

5d5bd9951e26: Image successfully pushed

99da72cfe067: Image successfully pushed

1722f41ddcb5: Image already exists

5b74edbcaa5b: Image successfully pushed

676c4a1897e6: Image successfully pushed

07f8e8c5e660: Image already exists

37bea4ee0c81: Image successfully pushed

a82efea989f9: Image successfully pushed

e9e06b06e14c: Image successfully pushed

latest: digest: sha256:a2e441ff31d2fe62938075525bd63ac03dc47ae9d4a5682d20f36cae94f4ba02 size: 18390


도커허브의 프로파일로 가보면 새로운 이미지를 확인할 수 있다.



Step 2: Pull your new image


마지막으로 당신이 푸쉬한 이미지를 풀해보겠다. 수행하기전에 로컬 머신에 있는 오리지날 이미지를 삭제할 필요가 있다. 만약 로컬 머신에 이미지가 남아 있다면 도커는 풀하지 않을 것이다. - 왜냐? 두 이미지가 같기 때문이다.



로컬 머신에 있는 이미지를 확인해보자.


$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

hello-world         latest              af340544ed62        5 months ago        960 B

docker/whalesay     latest              fb434121fc77        8 months ago        247 MB

devsun98/whalesay   latest              fb434121fc77        8 months ago        247 MB


도커 rmi 명령을 이용해서 docker/whalesay 이미지와 devsun98/whalesay 이미지를 모두 삭제해보자.


아이디 또는 이름으로 삭제할 수 있다. 


$ docker rmi -f fb434121fc77

$ docker rmi -f whalesay


도커 pull 명령으로 리파지토리부터 새로운 이미지를 풀해보자.


로컬 머신에는 이미지가 없기때문에 도커는 다운로드할 것이다. 


$ docker pull devsun98/whalesay

Using default tag: latest

latest: Pulling from devsun98/whalesay

e9e06b06e14c: Pull complete

a82efea989f9: Pull complete

37bea4ee0c81: Pull complete

07f8e8c5e660: Pull complete

676c4a1897e6: Pull complete

5b74edbcaa5b: Pull complete

1722f41ddcb5: Pull complete

99da72cfe067: Pull complete

5d5bd9951e26: Pull complete

fb434121fc77: Pull complete

Digest: sha256:a2e441ff31d2fe62938075525bd63ac03dc47ae9d4a5682d20f36cae94f4ba02

Status: Downloaded newer image for devsun98/whalesay:latest




반응형
반응형

당신이 어떤 좋은 것을 만들었다면 그것을 공유할 수 있다. 이번 섹션에서는 우리는 공유를 해볼것이다. Docker Hub account가 필요할 것이다. 그러면 당신의 이미지를 푸쉬해서 다른 사람들이 도커에서 실행할 때 사용할 수 있게 할 수 있다.


Step 1: 계정 만들기 


브라우저에서 도커허브 singup 페이지로 이동하자.


다음과 같은 페이지가 출력될 것이다. 




singup 페이지에 형식을 채우자.


도커 허브는 무료이다. 도커는 이름, 패스워드 이메일 주소가 필요하다.


Signup을 누르자.


도커허브 웰컴페이지가 출력될 것이다.


Step 2: 이메일 검증 및 리파지토리 추가하기


어떤것을 허브에 공유하기 전에 이메일이 맞는지 확인할 필요가 있다.


이메일 받은편지함에 가보자.


이메일의 제목이 다음과 같은 것을 찾자. "Please confirm email for your Docker Hub account"


만약 이메일이 보이지 않는다면 스팸편지함이나 조금더 기다려보자.


이메일을 열고 Confirm Your Email 버튼을 클릭하자.


브라우저는 당신의 프로파일 페이지를 열것이다.


Create Repository를 선택하자. 




리파지토리 명과 간략 설명을 채우자.


Visibility를 Public으로 설정하자. 


Create 버튼을 눌러서 완료하자.


도커허브에 당신의 새로운 리파지토리가 생성되었다.


반응형
반응형

Step 1: Write a Dockerfile


이번 스텝에서는 Mac의 텍스트에디터를 사용해 짧은 도커 파일을 작성해보겠다. Dockerfile은 이미지로 구워질 소프트웨어를 묘사한다. 단지 재료로서 만이 아니라 사용되기 위해 어떤 환경인지 또는 실행하기 위한 어떤 명령이든지 다 기술할 수 있다. 작성법은 매우 짧을 것이다.


만약 터미널이 오픈되어 있지 않다면 먼저 오픈을 하기 바란다.


1. 먼저 새로운 디렉토리를 만들자 


$ mkdir mydockerbuild


이 디렉토리는 빌드를 위한 context로서 제동될 것이다. context 의미는 이미지를 빌드하기 위해 필요한 모든 것들을 포함하고 있다는 것이다.


2. 새로운 디렉토리로 이동하자. 


$ cd mydockerbuild


지금은 디렉토리가 비어 있을 것이다. 


3. 디렉토리에 Dockerfile을 생성하자.


$ touch Dockerfile


이 커맨드는 실제로 아무일도 하지 않고 현재 디렉토리에 Dockerfile을 생성할 것이다.  다음 명령으로 제대로 생성되었는지 확인해보자.


$ ls Dockerfile

Dockerfile


4. 이제 Dockerfile을 열고 다음과 같은 내용을 작성해보자.


FROM docker/whalesay:latest


RUN apt-get -y update && apt-get install -y fortunes


CMD /usr/games/fortune -a | cowsay


FROM 키워드는 Docker가 어떤 이미지를 베이스로 이미지를 생성할지를 의미한다. 여기서는 기존에 존재하는 whalesay 이미지를 베이스로 생성한다. 


두번쨰 라인은 fortune 프로그램을 이미지에 추가하는 것이다. 이 라인은 apt-get를 이용하여 fortune 프로그램을 추가하는 것이다. 


이미지에 필요한 소프트웨어가 설치되었다면 이미지가 로드되었을때 소프트웨어를 실행하라고 지시해야 한다.


세번째 라인은 fortune 프로그램에게 cowsay 프로그램으로 nifty quotes를 전송하라고 하는 것이다.


이제 새로운 이미지를 빌드할 준비가 된것이다. 


Step 2: Build an image from your Dockerfile


현재 디렉토리에 도커파일이 있는지 확인하기 위해 cat 명령을 수행해보자.

$ cat Dockerfile

FROM docker/whalesay:latest



RUN apt-get -y update && apt-get install -y fortunes



CMD /usr/games/fortune -a | cowsay


이제 docker build -t docker-whale . 이라는 명령을 수행해보자.

$ docker build -t docker-whale .

Sending build context to Docker daemon 2.048 kB

Step 0 : FROM docker/whalesay:latest

 ---> fb434121fc77

Step 1 : RUN apt-get -y update && apt-get install -y fortunes

 ---> Running in dea12fa9ff26

... 중략 ...

Removing intermediate container 816e9f429d28

Successfully built e6181174002b


이 명령은 실행되고 결과를 출력하는데 수초가 소요된다. 새로운 이미지와 무언가를 하기전에 Dockerfile의 빌드 프로세스에 대해서 살펴보자.


Step 3: Learn about the build process


"docker build -t docker-whale ." 명령은 현재 디렉토리내의 Dockerfile을 획득한다. 그리고 docker-whale이라고 불리는 이미지를 당신의 로컬 머신에 생성한다. 이 명령은 몇분이 소요되고 그 추력은 실제로 길고 복잡하다. 이번 세션에서는 각 메시지가 의미하는 바에 대해 살펴보겠다.


먼저 도커가 빌드에 필요한 모든 것들에 대해서 체크한다.

Sending build context to Docker daemon 158.8 MB


그리고 도커는 whalesay 이미지를 로드한다. 이미 다운 받았다면 스킵하고 로컬에 없다면 다운로드를 받을 것이다.

Step 0 : FROM docker/whalesay:latest

 ---> fb434121fc77



도커는 다음 스텝으로 가서 apt-get 패키지 매니저를 통해 업데이트를 수행한다. 설치 라인은 엄청 길다. 여기서 다시 모두를 언급하진 않겠다.

Step 1 : RUN apt-get -y update && apt-get install -y fortunes

 ---> Running in 27d224dfa5b2

Ign http://archive.ubuntu.com trusty InRelease

Ign http://archive.ubuntu.com trusty-updates InRelease

Ign http://archive.ubuntu.com trusty-security InRelease

Hit http://archive.ubuntu.com trusty Release.gpg

....snip...

Get:15 http://archive.ubuntu.com trusty-security/restricted amd64 Packages [14.8 kB]

Get:16 http://archive.ubuntu.com trusty-security/universe amd64 Packages [134 kB]

Reading package lists...

---> eb06e47a01d2


그런 다음 도커는 새로운 fortunes 소프트웨어를 설치한다.

Removing intermediate container e2a84b5f390f

Step 2 : RUN apt-get install -y fortunes

 ---> Running in 23aa52c1897c

Reading package lists...

Building dependency tree...

Reading state information...

The following extra packages will be installed:

  fortune-mod fortunes-min librecode0

Suggested packages:

  x11-utils bsdmainutils

The following NEW packages will be installed:

  fortune-mod fortunes fortunes-min librecode0

0 upgraded, 4 newly installed, 0 to remove and 3 not upgraded.

Need to get 1961 kB of archives.

After this operation, 4817 kB of additional disk space will be used.

Get:1 http://archive.ubuntu.com/ubuntu/ trusty/main librecode0 amd64 3.6-21 [771 kB]

...snip......

Setting up fortunes (1:1.99.1-7) ...

Processing triggers for libc-bin (2.19-0ubuntu6.6) ...

 ---> c81071adeeb5

Removing intermediate container 23aa52c1897c


마침내 빌드를 완료하고 리포트를 출력한다.

Step 3 : CMD /usr/games/fortune -a | cowsay

 ---> Running in a8e6faa88df3

 ---> 7d9495d03763

Removing intermediate container a8e6faa88df3

Successfully built 7d9495d03763



Step 4: Run your new docker-whale


이번 스텝에서는 로컬 머신에 새로운 이미지가 생겼는지 그리고 새로운 이미지를 어떻게 실행하는지에 대해 살펴보겠다.

docker images 커맨드로 로컬에 설치된 이미지 리스트를 확인하자.


$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

docker-whale        latest              e6181174002b        9 minutes ago       274.3 MB

hello-world         latest              af340544ed62        5 months ago        960 B

devsun98/whalesay   latest              fb434121fc77        8 months ago        247 MB

docker/whalesay     latest              fb434121fc77        8 months ago        247 MB


마지막으로 새로운 이미지를 실행해보자.

$ docker run docker-whale

 ______________________________________

/ Wasting time is an important part of \

\ living.                              /

 --------------------------------------

    \

     \

      \

                    ##        .

              ## ## ##       ==

           ## ## ## ##      ===

       /""""""""""""""""___/ ===

  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~

       \______ o          __/

        \    \        __/

          \____\______/



반응형
반응형

전세계 많은 사람들이 도커 이미지를 생성한다. 우리는 도커 허브에 접속해서 이러한 이미지들을 발견할 수 있다. 이번 섹션에서는 이미지를 찾고 사용하는 방법에 대해서 알아보겠다.


Step 1: Locate the whalesay image


브라우저를 열고 도커 허브에 접속하자.



도커허브는 개인들 뿐만아니라 RedHat, IBM, Google과 같은 기관의 공식이미지들도 포함하고 있다


2, 위에 표시된 서치 바에 whalesay라는 단어를 입력해보자.



3. 결과중에 docker/whalesay를 클릭하자. 


브라우져는 whalesay 이미지에 대한 리파지토리를 출력할 것이다.



각 이미지 리파지토리는 이미지에 대한 정보를 포함하고 있다. 어떤종류의 소프트웨어 이미지를 포함하고 있고 어떻게 사용하는지 등이다. 내용을 보면 whalesay 이미지는 Ubuntu라고 불리는 Linux 배포판에 기반을 하고 있다는 것을 알 수 있다. 다음 스텝에서 우리의 머신에서 whalesay이미지를 실행해보자.


Step 2: Run the whalesay image


1, 런치패드를 열고 Quickstart Terminal icon을 선택하자.


2. 터미널에서 docker run docker/whalesay cowsay boo 라는 커맨드를 입력하고 엔터를 쳐라.


3. 이 명령어는 whalesay 이미지를 컨테이너에 실행하는 것이다. 터미널은 다음과 같은 내용을 출력할 것이다.


toddsonui-MacBook-Pro:~ devsun$ docker run docker/whalesay cowsay boo

Unable to find image 'docker/whalesay:latest' locally

latest: Pulling from docker/whalesay

e9e06b06e14c: Pull complete

a82efea989f9: Pull complete

37bea4ee0c81: Pull complete

07f8e8c5e660: Pull complete

676c4a1897e6: Pull complete

5b74edbcaa5b: Pull complete

1722f41ddcb5: Pull complete

99da72cfe067: Pull complete

5d5bd9951e26: Pull complete

fb434121fc77: Already exists

Digest: sha256:178598e51a26abbc958b8a2e48825c90bc22e641de3d31e18aaf55f3258ba93b

Status: Downloaded newer image for docker/whalesay:latest

 _____

< boo >

 -----

    \

     \

      \

                    ##        .

              ## ## ##       ==

           ## ## ## ##      ===

       /""""""""""""""""___/ ===

  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~

       \______ o          __/

        \    \        __/

          \____\______/



4. 다음은 docker images라는 명령어를 수행해보자. 다음과 같은 내용이 출력될 것이다.


toddsonui-MacBook-Pro:~ devsun$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

hello-world         latest              af340544ed62        8 weeks ago         960 B

docker/whalesay     latest              fb434121fc77        4 months ago        247 MB


컨테이너에 이미지를 실행하면 도커는 당신의 컴퓨터에 이미지를 다운로드 한다. 이 로컬 이미지 복사본은 시간을 절약해준다. 도커는 허브의 이미지 소스 변경이 없다면 이미지를 다시 다운로드 하지 않을 것이다. 물론 이미지를 삭제할 수도 있다. 


5. whalesay 컨테이너와 조금 다른 것을 해보자. docker run docker/whalesay cowsay boo-boo 라고 명령을 내리면 이전처럼 다운로드 받지 않고 빠르게 수행됨을 알 수 있다.


toddsonui-MacBook-Pro:~ devsun$ docker run docker/whalesay cowsay boo-boo

 _________

< boo-boo >

 ---------

    \

     \

      \

                    ##        .

              ## ## ##       ==

           ## ## ## ##      ===

       /""""""""""""""""___/ ===

  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~

       \______ o          __/

        \    \        __/

          \____\______/


반응형

'Programming > Docker' 카테고리의 다른 글

Docker - Create a Docker Hub account & repository  (0) 2016.02.02
Docker - Build your own imag  (0) 2015.10.12
Docker - Images & Containers  (0) 2015.10.02
Docker - 설치  (0) 2015.04.29
Docker - 개요  (0) 2015.04.29
반응형

지난 시간 마지막 스텝에서 우리는 docker run hello-world라는 명령을 수행하였다. 하나의 커맨드내에서 도커를 사용하기 위한 핵심 타스크들이 완료되었다. 커맨드는 다음과 같이 세가지 파트로 나누어진다.





컨테이너는 리눅스 오퍼레이팅 시스템의 가장 기본적인 기능만을 가진 버젼이다. 이미지는 컨테이너내에서 로딩될 소프트웨어이다. 커맨드를 수행시키면 도커 소프트웨어에서 다음과 같은 이벤트가 발생한다.


  • hello-world 소프트웨어 이미지를 가지고 있는지 확인한다.
  • 없다면 도커 허브로부터 이미지를 다운로드한다.
  • 컨테이너로 이미지는 로드되고 실행된다. 


구성에 따라 이미지는 단순하게 하나의 커맨드를 실행하고 종료된다. 이것이 Hello-World가 실행된 것이다.


도커 이미지는 더욱 많은 기능을 가지고 있다. 이미지는 복잡한 데이터베이스처럼 소프트웨어를 시작할 수 있다. 나중에 사용하기 위해 데이터를 추가하고 저장할 수 있으며, 또 다른 사람을 위해 대기할 수도 있다.


그러면 hello-world 이미지는 누가 만든 것인가? 이 경우 도커가 했지만 아무나 가능하다. 도커는 사람들이 도커 이미지를 통해 소프트웨어를 생성하고 공유하도록 도와준다. 도커를 이용하면 더이상 당신의 컴퓨터에서 도커 이미지를 실행할 수 있을지를 걱정하지 않아도 된다. 도커 컨테이너가 항상 수행해주기 때문이다.

반응형

'Programming > Docker' 카테고리의 다른 글

Docker - Build your own imag  (0) 2015.10.12
Docker - whalesay 이미지 찾아서 실행하기  (0) 2015.10.07
Docker - 설치  (0) 2015.04.29
Docker - 개요  (0) 2015.04.29
Docker - 소개  (0) 2015.04.28

+ Recent posts