docker registry로 도커 컨테이너 관리하기

[markdown]
docker-registry

보통은 서버의 형상관리를 chef로 관리하지만,
소스를 배포할 때에 하나의 이미지로 뭉쳐서 배포를 해보고 싶어서
docker를 도입해보려고 공부중이다.

그런데 내가 생성한 이미지를 docker hub라는 열린 docker registry
올릴 수는 없어서, 찾아본것이 docker registry였다.

책이나 블로그에서 그다지 심도있게 다루고 있지 않아서, 쉬운가보다 했는데,
왠걸 설치가 생각보다 까다로웠다.

디지털오션의 글이 정말 많이 도움이 됐는데, 거기 있는 글을 보고
내용을 조금 추가, 수정 한것이라 보시면 될 것 같다.

모쪼록 docker registry를 도입하고자 하는 사람이 이 글을 보고 조금이나마 쉽게
구축 할 수 있으면 좋겠다.

시작하기 전에…

  • ubuntu를 사용 (14.04 면 좋음)
  • docker와 docker compose는 설치가 되어 있어야함
  • docker registry에서 사용할 도메인이 있어야함

docker 설치

설치전에 해야할 것들

뭔가 귀찮은게 많이 있는데, 그냥 빨리 설치하고 싶은 사람은 아래에 설.치. 부분으로 바로 이동하자.
시간이 있는 사람들은 봐두면 나중에 도움이 되는 부분은 있을 것 같다.

[code lang=text]
$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates
$ sudo apt-key adv –keyserver hkp://p80.pool.sks-keyservers.net:80 –recv-keys 58118E89F3A912897C070ADBF76221572C52609D
$ sudo /etc/apt/sources.list.d/touch docker.list
[/code]

우분투의 다른 버전이라면 docker.list파일에 아래의 내용으로 변경하자

[code lang=text]
### ubuntu 12.04
deb https://apt.dockerproject.org/repo ubuntu-precise main

### ubuntu 14.04
deb https://apt.dockerproject.org/repo ubuntu-trusty main

### ubuntu 15.10
deb https://apt.dockerproject.org/repo ubuntu-wily main
[/code]

[code lang=text]
### `APT` 패키지의 인덱스를 업데이트
$ sudo apt-get update

### 오래된 버전 삭제
$ sudo apt-get purge lxc-docker

### `APT`확인하기
$ sudo apt-cache policy docker-engine
[/code]

linux-image-extra 설치

[code lang=text]
$ sudo apt-get install linux-image-extra-$(uname -r)
$ sudo apt-get install apparmor
$ sudo apt-get install docker-engine
[/code]

설.치.

위에 주저리 주저리 많은데, 보통은 이것만 해도 설치가 된다.

[code lang=text]
$ sudo apt-get update
$ sudo apt-get install docker-engine
$ sudo service docker start
$ sudo docker run hello-world
[/code]

요즘에 도커를 설치할 일이 많아서, 아래의 링크에 설치 스크리트를 정리해 두었다.

도커 설치 스크립트

docker compose 설치

[code lang=text]
$ sudo apt-get -y install python-pip
$ sudo pip install docker-compose
[/code]

docker compose 테스트

[code lang=text]
$ cd ~/docker-registry/
$ mkdir hello-world
$ cd hello-world
$ vi docker-compose.yml
[/code]

docker-compose.yml을 아래와 같이 만들자.

[code lang=text]
test-compose:
image: hello-world
[/code]

테스트

[code lang=text]
$ sudo docker-compose up
[/code]

아래와 같이 나오면 성공이다.

[code lang=text]
Creating helloworld_test-compose_1
Attaching to helloworld_test-compose_1
test-compose_1 |
test-compose_1 | Hello from Docker.
test-compose_1 | This message shows that your installation appears to be working
………. 블라블라……………..
test-compose_1 |
helloworld_test-compose_1 exited with code 0
[/code]

docker-registry 설치에 docker-compose가 이용되는 것이므로
docker-compose에 대해 더 알고 싶은 사람은 아래 링크를 참고하자.

Docker compose

서버와 클라이언트의 버전이 다르다고 나올 때

아래와 같은 메세지가 나오는 경우가 있는데,
아래의 경우 클라이언트가 서버보다 새로운 버전이라 나는 에러이니
설치된 오래된 docker를 삭제하고 새로운 버전으로 다시 설치하자.

[code lang=text]
ERROR: client and server don't have same version (client : 1.21, server: 1.18)
[/code]

아래의 메세지로 도커에 대한 정보를 알 수 있다.

[code lang=text]
$ docker version
$ docker info
[/code]

패스워드 생성을 위한 패키지 설치

apache2-utils에 있는 htpasswd 를 사용하기위한 패키지 다운로드

[code lang=text]
### kr.archive.ubuntu.com 에서는 패키지를 잘 못받아 오는 경우가 있으므로 변경해줌
$ sudo sed -i 's/kr.archive.ubuntu.com/ftp.daum.net/g' /etc/apt/sources.list
$ sudo apt-get update
$ sudo apt-get -y install apache2-utils
[/code]

Docker Registry 설치 및 설정하기

두개의 컨테이너를 연결할때 docker-compose를 사용할 것이다.
docker-compose.yml에 정의 된 내용을 설정 파일로 사용한다.

도커 레지스트리에서 사용할 디렉토리를 생성한다.

[code lang=text]
$ mkdir ~/docker-registry && cd $_
$ mkdir data
[/code]

docker-registry를 만들기위한 docker-compose.yml 파일을 아래와 같이 생성한다.

[code lang=text]
registry:
image: registry:2
ports:
– 127.0.0.1:5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
– ./data:/data
[/code]

아래의 명령어로 docker-registry 를 띄우자.

[code lang=text]
$ cd ~/docker-registry
$ sudo docker-compose up
[/code]

아래와 같은 메세지들이 나온다.

[code lang=text]
Attaching to dockerregistry_registry_1
registry_1 | time="2016-02-19T02:34:50Z" level=warning msg="No HTTP secret provided – generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.5.3 instance.id=840ceb15-6c68-41b2-a793-967ee3974a20 version=v2.3.0
registry_1 | time="2016-02-19T02:34:50Z" level=info msg="redis not configured" go.version=go1.5.3 instance.id=840ceb15-6c68-41b2-a793-967ee3974a20 version=v2.3.0
registry_1 | time="2016-02-19T02:34:50Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.5.3 instance.id=840ceb15-6c68-41b2-a793-967ee3974a20 version=v2.3.0
registry_1 | time="2016-02-19T02:34:50Z" level=info msg="listening on [::]:5000" go.version=go1.5.3 instance.id=840ceb15-6c68-41b2-a793-967ee3974a20 version=v2.3.0
registry_1 | time="2016-02-19T02:34:50Z" level=info msg="Starting upload purge in 55m0s" go.version=go1.5.3 instance.id=840ceb15-6c68-41b2-a793-967ee3974a20 version=v2.3.0
[/code]

No HTTP secret provided라는 문구에 놀라지 말라고 한다. 정상이라고~

아무튼 저 메세지가 나오면 잘 된것이니 Ctrl + C를 눌러서 빠져 나가자.
registry 하나 올리려고 docker-compose를 깐게 아니다.

Nginx 설정하기

[code lang=text]
$ mkdir ~/docker-registry/nginx
[/code]

docker-compose.yml파일을 다시 열어서 아래의nginx 관련 설정을 추가하자.

[code lang=text]
nginx:
image: "nginx:1.9"
ports:
– 5443:443
links:
– registry:registry
volumes:
– ./nginx/:/etc/nginx/conf.d
[/code]

결과적으로 docker-compose.yml은 아래와 같은 형태가 된다.

[code lang=text]
nginx:
image: "nginx:1.9"
ports:
– 5443:443
links:
– registry:registry
volumes:
– ./nginx/:/etc/nginx/conf.d
registry:
image: registry:2
ports:
– 127.0.0.1:5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
– ./data:/data
[/code]

그런데 nginx의 설정파일이 빠져있으므로 추가하자.

nginx 설정파일 추가하기

아래의 경로에 설정파일을 추가하자.

[code lang=text]
$ vi ~/docker-registry/nginx/registry.conf
[/code]

설정은 아래와 같다.

[code lang=text]
### registry.conf

upstream docker-registry {
server registry:5000;
}

server {
listen 443;
server_name docker.gyus.me;

client_max_body_size 0;
chunked_transfer_encoding on;

location /v2/ {
### docker 1.5 버전 이하에서 접속 안되게 함.
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
return 404;
}

proxy_pass http://docker-registry;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}
[/code]

$ docker-compose up으로 서버를 올릴 때 아래와 같은 에러가 났는데,

[code lang=text]
ERROR: failed to register layer: Untar re-exec error: unexpected EOF: output:
[/code]

sudo로 권한을 높여주니 해결 됐다. 압축을 풀 권한이 없는 곳에 압축을 풀려다가 에러가 난것 같다.

[code lang=text]
$ sodo docker-compose up
[/code]

nginx 랑 잘 연동이 되었는지 curl로 확인해보자.

[code lang=text]
$ curl http://localhost:5000/v2/
[/code]

{} 로 결과 값이 나오면 성공이다.

https가 바인딩되는 포트로 사용될 5443 포트로도 잘 되는지 확인해 보자.

[code lang=text]
$ curl http://localhost:5443/v2/
[/code]

역시나 {} 로 결과 값이 나오면 성공이다.

인증 설정하기

SSL만으로 불안한 사람은 이걸 하는게 좋은 것 같다.
나는 귀찮아서 사실 패스했다.

htpasswd 파일을 생성해보자.

[code lang=text]
$ cd ~/docker-registry/nginx
$ htpasswd -c registry.password <유저명>

### 패스워드를 입력해야한다. (안입력해도 되긴된다.)
New password:
Re-type new password:
[/code]

nginx설정파일인 registry.conf 파일에 인증관련 설정을 추가해주자.
location 항목 아래에 설정해주어야한다.

[code lang=text]
location /v2/ {
#### docker 1.5 버전 이하에서 접속 못하도록 막기.
if ($http_user_agent ~ "^(docker\1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
return 404;
}

#### 인증 설정
auth_basic "registry.localhost";
auth_basic_user_file /etc/nginx/conf.d/registry.password;
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

proxy_pass http://docker-registry;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
[/code]

SSL 세팅하기

nginx 설정파일인 ~/docker-registry/nginx/registry.conf 파일에 SSL 인증 관련 설정을 추가하자.
SSL인증을 위해서는 해당도메인의 인증서 파일인 crt파일과 key파일이 필요하다.

[code lang=text]
server {
listen 443;
server_name deploy.gyus.me;

# SSL
ssl on;
ssl_certificate /etc/nginx/conf.d/domain.crt;
ssl_certificate_key /etc/nginx/conf.d/domain.key;
[/code]

인증서와 키파일은 startssl 사이트에서 공짜로 얻을 수도 있고,
다른 인증기관에서 구매도 가능하다.

임시적으로 사용하기 위해서 자가 인증서를 발급 하는 방법도 있는데, 아래에서 알아보자.

자가 인증서 발급하기

도커에서는 자가인증서만 가지고는, SSL를 사용할 수가 없고
자가 인증서를 인증해주는 자가 인증기관도 우리 서버에 세팅을 해야한다;;

자가인증기관에서 인증해줄수 있도록 루트 인증키를 만들자.

[code lang=text]
$ cd ~/docker-registry/nginx
### 루트 키를 만들자.
$ openssl genrsa -out rootCA.key 2048
### 루트 인증키를 만들자. (물어보는거는 대충 알아서 잘 적도록하자.)
$ openssl req -x509 -new -nodes -key rootCA.key -days 10000 -out rootCA.crt
[/code]

이제 우리 서버의 인증서를 만들어보자.

[code lang=text]
### 키파일을 만든다.
$ openssl genrsa -out gyusme.key 2048
### 인증서 서명 요청 파일을 만듬 (csr)
$ openssl req -new -key gyusme.key -out gyusme.csr
### 인증서를 생성
$ openssl x509 -req -in gyusme.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out gyusme.crt -days 10000
[/code]

인증서 서명 요청 파일 (csr)을 만들때에 이것 저것 물어보는데, 다른 건 몰라도 도메인은 잘 입력해주도록 하자.
그리고 패스워드를 물어보면 그냥 엔터 를 치자

[code lang=text]
Country Name (2 letter code) [AU]:KO
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:Busan
Organization Name (eg, company) [Internet Widgits Pty Ltd]:gyus,inc.
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:docker.gyus.me
Email Address []:
A challenge password []:
An optional company name []:
[/code]

여기까지 했다면 nginx디렉토리에는 아래와 같은 파일들이 있을 것이다.

[code lang=text]
-rw-rw-r– 1 ubuntu ubuntu 1229 Feb 19 17:29 gyusme.crt
-rw-rw-r– 1 ubuntu ubuntu 1054 Feb 19 17:28 gyusme.csr
-rw-rw-r– 1 ubuntu ubuntu 1679 Feb 19 17:26 gyusme.key
-rw-rw-r– 1 ubuntu ubuntu 831 Feb 19 17:10 registry.conf
-rw-rw-r– 1 ubuntu ubuntu 1269 Feb 19 17:25 rootCA.crt
-rw-rw-r– 1 ubuntu ubuntu 1675 Feb 19 17:25 rootCA.key
-rw-rw-r– 1 ubuntu ubuntu 17 Feb 19 17:29 rootCA.srl
[/code]

우리의 서버가 인증기관인것 처럼 동작하게 하는 세팅을 해주자.

[code lang=text]
$ sudo mkdir /usr/local/share/ca-certificates/docker-cert
$ sudo cp rootCA.crt /usr/local/share/ca-certificates/docker-cert
$ sudo update-ca-certificates
[/code]

SSL 테스트하기

테스트를 해보려면, SSL 설정까지 마치고 에러없이 docker registrynginx가 올라가야 한다.

[code lang=text]
$ cd ~/docker-registry
$ docker-compose up
[/code]

[code lang=text]
### 기본인증 사용X, 자가 인증서 X 인 경우
$ curl https://domain:5443/v2/

### 기본인증 사용 O, 자가 인증서 X 인 경우
$ curl https://USERNAME:PASSWORD@domain:5443/v2/

### 기본인증 사용 O, 자가 인증서 O 인 경우
$ curl https://USERNAME:PASSWORD@domain:5443/v2/ -k
[/code]

도커 레지스트리 서비스로 등록하기

도커 레지스트리를 운영하는 서버를 재시작 할 경우가 생길 수 있는데,
이때에 필요한 프로세스를 일일이 찾아서 올리는거는 많은 정신력을 필요로 한다.

그런일을 당하지 않도록 서비스로 등록해보자.

Upstart 스크립트를 작성해서, 시스템이 부팅될 때 시작되도록 해보자.

[code lang=text]
$ cd ~/docker-registry
### 지금 올라간 컨테이너를 삭제
$ docker-compose rm
$ sudo mv ~/docker-registry /docker-registry
$ sudo chown -R root: /docker-registry
[/code]

Upstart스크립트를 작성해보자.

[code lang=text]
$ sudo vi /etc/init/docker-registry.conf
[/code]

[code lang=text]
### docker-registry.conf
description "Docker Registry"

start on runlevel [2345]
stop on runlevel [016]

respawn
respawn limit 10 5

chdir /docker-registry

exec /usr/local/bin/docker-compose up
[/code]

이제 docker-registry를 실행 시켜보자.

[code lang=text]
$ sudo service docker-registry start
[/code]

아래와 같이 나오면 성공이다.

[code lang=text]
docker-registry start/running, process 27241
[/code]

아래의 명령어로 또한 확인이 가능하다.

[code lang=text]
$ docker ps
[/code]

로그는 아래의 명령어로 확인이 가능하다.

[code lang=text]
$ sudo tail -f /var/log/upstart/docker-registry.log
[/code]

curl 명령어로 확인을 하면 nginx_1이 앞에 붙어서 로그가 찍힐 것이다.

[code lang=text]
$ curl https://USERNAME:PASSWORD@domain:5443/v2/
[/code]

클라이언트 머신에서 docker registry 접근하기

다른 머신에서 도커 레지스트리에 접속하려면 루트인증서 파일을 해당 서버에 등록해주어야 한다.

[code lang=text]
$sudo cat /docker-registry/nginx/rootCA.crt
[/code]

위의 명령어를 실행하면 아래와 같은 형식의 암호화 문자열이 나올것이다.

[code lang=text]
—–BEGIN CERTIFICATE—–
MIIDfTCCAmWgAwIBAgIJAKJf+hKlYzotMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV
…. 중략…
ShmxzUJQAcQwdI2Wrivv9QG4kcRPw73lrMTNU8FfYnfQ
—–END CERTIFICATE—–
[/code]

이걸 docker registry서버의 머신에서 해주었던 것 처럼 등록해주어야 한다.

우분투의 경우

[code lang=text]
$ sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert
$ sudo cp rootCA.crt /usr/local/share/ca-certificates/docker-dev-cert/
$ sudo update-ca-certificates
[/code]

Centos의 경우

[code lang=text]
$ sudo cp rootCA.crt /etc/pki/ca-trust/source/anchors/
$ sudo update-ca-trust enable
$ sudo update-ca-trust extract
[/code]

루트 인증서를 추가후 도커를 재시작 해야한다.

[code lang=text]
$ sudo service docker restart
[/code]

인증을 사용하는 경우 docker login을 사용해야 하는데, 사용법은 아래와 같다.

[code lang=text]
$ docker login https://<domain>
[/code]

UsernamePassword Email을 물어보는데, Email은 그냥 아무것도 입력 하지 않으면 된다.

성공인 경우 아래와 같은 메세지가 뜬다.

[code lang=text]
Login Succeeded
[/code]

이미지를 올려보자.

가장 쉬운 hello-world로 해보자.

[code lang=text]
$ sudo docker run hello-world
$ sudo docker tag hello-world deploy.gyus.me:5443/hello-world
$ sudo docker push deploy.gyus.me:5443/hello-world
[/code]

위와 같은 스크립트를 실행시키면 성공시에 아래와 같은 메세지들이 나온다.

[code lang=text]
The push refers to a repository [deploy.gyus.me:5443/hello-world]
5f70bf18a086: Pushed
b652ec3a27e7: Pushed
latest: digest: sha256:fea8895f450959fa676bcc1df0611ea93823a735a01205fd8622846041d0c7cf size: 708
[/code]

다른 머신에서 이미지를 땡겨와보자.

땡겨오는 법은 그냥 push 대신 pull을 쓰면 된다.
물론 인증서 작업은 완료된 상태이어야 한다.

[code lang=text]
$ docker pull deploy.gyus.me:5443/hello-world
[/code]

[code lang=text]
$ docker run deploy.gyus.me:5443/hello-world
[/code]

잘 실행된다!

[code lang=text]
Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
https://hub.docker.com

For more examples and ideas, visit:
https://docs.docker.com/userguide/
[/code]

느낀점

처음에는 좀 어렵다 귀찮다라는 느낌이 강했는데,
차근 차근 설치해보니, 크게 어려운 점은 없었다.

https로 통신을 해야하니 자가인증기관과 자가인증서를 만들어 주는 부분을
처음 해보는거라서 좀 이상하긴 했지만, 이 부분은 나중에 또 공부를 해야되는 부분으로
남겨두기로 한다.

참고 링크

아래의 링크를 대부분 참고했고, 따라하면서 내용을 조금씩 추가하거나 생략 하거나 했다.
디지탈 오션

추가 (인증서 인증 실패 관련)

자가인증서를 사용하게 되면, 아래와 같은 에러가 나는 경우가 있다.

[code lang=text]
tls: oversized record received with length 20527
[/code]

이런경우 /etc/docker/certs.d/domain:5443 의 경로에
위에서 만든 rootCA.crt 파일을 복사한후 도커를 재시작 해주면 된다.
자세한 것은 아래의 링크를 참고하자.

https://docs.docker.com/registry/insecure/

[/markdown]

docker 명령어들

[markdown]

# docker 명령어들

도커로 apache php mysql환경을 구성중이다.
apache와 php를 하나의 환경으로 묶기로 했고, mysql은 따로 하나더 묶을 예정이다.

이 글은 위의 환경을 구축중에 공부하고 있는 것들을 정리하는 글인데, 위의 환경 구축이 완료되면
관련해서 글을 하나 더 쓸 수 있을 것 같다.

도커가 간단하네 심플하네 빠르네, 이런 것들로 홍보를 하고 있지만,
알아야 될 것 들이 생각보다 많다.
명령어를 도저히 다 외울 수가 없어서 그냥 정리하기로 했다.

도커를 공부하면서 좋은 것 하나는 bash와 자동화에 대한 지식이 뽀너스로 늘어나는 것이 좋은 것 같다.
물론 알아야되는게 많아서 짜증나는 점이기도 하다.

오픈소스 홈페이지들에 올라가 있는 정보는 내가 보기에는 너무 상세하고 스펙적인게 대부분이기 때문에,
그냥 이렇게 케이스별로 정리를 하는게 나에게는 도움이 많이 되었던것 같다.

찾아보면 대부분 나오는 것들이겠지만,
도커를 하면서 조금이라도 삽질을 줄이려면, 자신만의 커맨드라인 리스트 같은게 있으면
개발할 때 좋을 것 같다.

아직 공부중이기 때문에 해당 포스트는 추후에 좀 더 내용이 추가될 가능성이 있다.

### 도커설치(우분투)

“`
$ sudo apt-get update
$ sudo apt-get install docker.io
“`

### 도커설치(Centos)

“`
$ sudo yum update
$ curl -fsSL https://get.docker.com/ | sh
$ sudo service docker start
“`

### 도커설치 윈도우, OSX

### docker 실행시 관리자 권한으로 실행되게 하기
매번 실행할때마다 sudo 넣는게 귀찮은 사람은 실행하면 좋다. (ubuntu에서는 잘되는데 cent에서는 잘 안됨!)

“`
$ sudo usermod -aG docker ${USER}
$ sudo service docker restart
“`

아래와 같은 에러가 나는 경우. 재부팅을 해주면 된다.
“`
FATA[0000] Post http:///var/run/docker.sock/v1.18/images/create?fromImage=registry%3Alatest: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?
“`

### docker 프로세스 모두 죽이기

“`
$ docker stop $(docker ps -qa)
“`

### docker 컨테이너 모두 삭제하기

가상머신에서 도커이미지를 만들게 되면, 용량이 부족하다고 가끔 뜨는데 그때 필요하다.

“`
$ docker rm $(docker ps -qa)
“`

### docker 이미지 모두 삭제하기
요것도 가상머신에서 용량이 부족하다고 뜰때 필요하다.
“`
$ docker rmi $(docker images -qa)
“`

### 도커 컨테이너 데몬모드로 시작시키기

“`
docker run -d image명
“`

### 도커 컨테이너에 배쉬연결

“`
docker run -it image명
“`

### 기존 ENTRYPOINT를 무시하고 entrypoint설정하기

“`
docker run –entrypoint=”/bin/bash”
“`

### 컨테이너끼리 연결하기

“`
docker run –link=”db:db” image명
“`

### 데몬모드로 띄우면서 포트, 볼륨, 환경설정까지 해보기

“`
docker run -d -p 8080:80 -v /home/user/www:/var/www -e PHP_ERROR_REPORTING=’E_ALL & ~E_STRICT’
“`
[/markdown]

Docker machine에 대하여

Mac에서 도커를 쓸려면 docker-machine 이라는 녀석을 무조건 써야되는데,
그냥 도커를 돌릴 수 있는 가상머신이라고 생각하니 마음이 편해졌다.
더 알고 싶으면, 밑에 글도 읽어보자.

아래 그림에서 Docker가 돌아가는 Linux VM이 docker-machine이라는 것이드아~

docker-machine
[gfm]
### Docker machine

– 도커 호스트가 설치된 VM이라고 생각하면 됨.
– VM이므로 개발PC, 클라우드, 데이터센터등 아무데나 설치가능
– 클라우드 서비스의 경우는 해당 클라우드의 서비스에 특성에 맞춰주는 driver가 존재함.
– 로컬에 설치하는 경우는 virtualbox, vmware를 지원함.
– 보통 Dooker toolbox로 설치하면 들어있음
– 명령어는 docker-machine 임
– 실제로 docker-machine을 만들고 start를 하면 mac에서는 virtualbox의 VM이 시작됨.

### Docker machine 생성하기
“`
$ docker-machine create –driver virtualbox dev
“`
create 명령으로 생성하는데, driver는 virtualbox가 기본값이고, aws, azure, digital ocean등등이 있다. 왜 이름이 드라이버인지는 아직 모르겠다.

“`
Running pre-create checks…
Creating machine…
(dev) Copying /Users/wapj/.docker/machine/cache/boot2docker.iso to /Users/wapj/.docker/machine/machines/dev/boot2docker.iso…
(dev) Creating VirtualBox VM…
(dev) Creating SSH key…
(dev) Starting the VM…
(dev) Waiting for an IP…
Waiting for machine to be running, this may take a few minutes…
Machine is running, waiting for SSH to be available…
Detecting operating system of created instance…
Detecting the provisioner…
Provisioning with boot2docker…
Copying certs to the local machine directory…
Copying certs to the remote machine…
Setting Docker configuration on the remote daemon…
Checking connection to Docker…
Docker is up and running!
To see how to connect Docker to this machine, run: docker-machine env dev
“`

실행결과를 살펴보면,

– boot2docker.iso를 카피한다음에 VM을 만들고
– ssh키를 만들고
– VM을 기동시키고, 네트웤이 올라오는걸 기다린다.
– 올라오면 boot2docker를 프로비저닝하고
– 인증키를 local -> remote 로 복사하고
– remote(여기서는 VM)에 있는 Docker daemon에 필요한 도커 설정을한다.
– 그뒤에 도커에 잘 접속되는지 체크한다.

docker-machine에 접속하기위한 정보를 보기위해서는

“`
$ docker-machine env dev
“`

를 실행하면 되고, 그 결과는 아래와 같다.

“`
export DOCKER_TLS_VERIFY=”1″
export DOCKER_HOST=”tcp://192.168.99.101:2376″
export DOCKER_CERT_PATH=”/Users/wapj/.docker/machine/machines/dev”
export DOCKER_MACHINE_NAME=”dev”
# Run this command to configure your shell:
# eval $(docker-machine env dev)
“`

도커 호스트의 ip와 포트 인증서의 위치, 도커 머신의 이름등이 나온다.

생성한 도커 머신을 확인하기
“`
$ docker-machine ls
“`

위의 명령어로 확인 하면 된다.

그리고 도커 머신과 정보를 주고받으려면 (이걸 공홈에서는 대화한다고 표현) 해당 도커머신에 대한 환경설정을 해야한다.

“`
$ eval “$(docker-machine env dev)”
$ docker ps
“`

해당 설정을 하지 않으면 도커 머신에 접속할 수 없다는 에러가 뜨게 된다.
Cannot connect to the Docker daemon. Is the docker daemon running on this host?

### 도커 머신에 이미지 실행하기

생성된 도커 머신에 이미지를 다운받고 실행해보자.

“`
$ docker run busybox echo hello world
Unable to find image ‘busybox:latest’ locally
latest: Pulling from library/busybox
583635769552: Pull complete
b175bcb79023: Pull complete
Digest: sha256:c1bc9b4bffe665bf014a305cc6cf3bca0e6effeb69d681d7a208ce741dad58e0
Status: Downloaded newer image for busybox:latest
hello world
“`

로컬에는 해당 이미지가 없기 때문에 docker hub에서 받아오게 (pull)되고, 해당 이미지를 실행한다.
도커머신의 ip를 알기 위해서는 아래와 같은 명령을 실행하면 되는데,
요즘 세상에는 머신의 아이피가 바뀌는건 부지기수로 있는 일이니 머신 이름으로 아이피를 받아오는 방법을 잘 알아놓는 것이 좋을 것이다.

“`
$docker-machine ip dev
192.168.99.101
“`

그럼 이제 nginx이미지를 받아서 실행해보고 잘되는지 확인해보자.
“`
$ docker run -d -p 8000:80 nginx
“`

위의 이미지를 실행하면 nginx를 다운받게 되고, -p 옵션으로 도커 호스트의 8000번 포트로 들어가게 되면, 컨테이너의 80번 포트로 포워딩을 해주게된다.

curl로 확인해보자

“`
$ curl `docker-machine ip dev`:8000



Welcome to nginx!


Welcome to nginx!

If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.

For online documentation and support please refer to
nginx.org.
Commercial support is available at
nginx.com.

Thank you for using nginx.



“`

도커 머신은 말그대로 VM이므로 여러개 생성이 가능하다.

아래의 기본적인 명령어는 일단 숙지를 하고 다니자.

“`
$ docker-machine create –driver virtualbox [이름]
$ docker-machine ls #리스트 보기
$ docker-machine stop [이름] # 정지시키기
$ docker-machine start [이름] # 시작하기
$ docker-machine rm [이름] # 삭제하기
“`
[/gfm]

도커 아키텍쳐

서버의 소스를 배포하려고 하는 중인데, 내가 알고 있는 방식은 파일을 동기화 시키는 방식이었다. docker를 사용하면, 여러개의 파일을 동기화 안하고 그냥 이미지로 구워서 할 수 있는 것 같아서, 소스 배포할 때 편할것 같은 느낌이 들었기 때문에 조사해보기로 했다. 아무래도 잘 모르는 기술을 잘 파악하기 위해서는 아키텍쳐를 알면 좋기 때문에 시간을 내서 아래의 페이지를 요약 번역 해보았다.

https://docs.docker.com/engine/introduction/understanding-docker/

마음대로 번역한거라 혹시 틀린내용이 있을 수 있는데,  잘못된 것을 발견하게 되면 바로 수정하겠음.

Why docker?

공홈에 보면 주저리주저리 많은데 내가 이해한 바는 아래 3가지이다.

  • 어플리케이션의 빠른 배포
    • 리눅스이기만 하다면 서버환경에 의존성이 없음
    • 우분투에서 센트OS환경의 이미지를 돌릴 수 있음. 당연히 반대로도 가능
  • 배포와 스케일아웃을 쉽게 해줌
  • 머신의 성능을 최대치 까지 뽑아낼 수 있음. (고밀도 -> 고성능)

도커의 아키텍쳐는 어째 되나?

도커는 클라이언트-서버 아키텍쳐를 사용한다.
클라이언트와 서버는 호스트 머신에 설치된 Docker daemon으로 빌드와 실행, 배포등을 할 수 있도록 통신한다.

docker architecture

 

도커 데몬

도커 데몬은 호스트 머신에서 실행되고, 유저는 Docker client를 통해서 데몬과 상호작용한다.

도커 클라이언트

도커 데몬에 명령을 내릴 수 있도록 만든 도커의 주된 유저 인터페이스이다.

도커 인사이드

내부를 이해하려면 다음의 3가지 Docker Images, Docker registries, Docker containers 를 알아야한다.

Docker images

도커 이미지는 읽기전용 템플릿이다. 예를들면, 우분투에 아파치 웹서버를 설치한 것을 하나의 이미지라고 볼 수 있다.
도커 이미지는 도커 컨테이너를 만드는데 사용되고, 도커는 새로운 이미지를 빌드할 수 있는 심플한 방법을 제공한다. 혹은 다른 사람이 만든것을 다운받을 수도 있다. 이미지는 도커의 빌드 컴포넌트이다.

Docker registries

도커 레지스트리는 이미지들을 보관하는 곳이다. 이미지를 업로드/다운로드 할 수 있는 공개 저장소와 사설 저장소가 있다. 공개 저장소는 Docker hub에서 제공되고 있다.
도커 레지스트리는 도커의 배포 컴포넌트이다.

Docker containers

도커 컨테이너는 디렉토리와 비슷하다. 도커 컨테이너는 어플리케이션을 실행하기 위한 모든것을 가지고 있다. 각각의 컨테이너는 하나의 도커 이미지로 만들어 진다.
도커 컨테이너는 실행될수 있고, 시작 시킬 수 있고, 중지 시킬 수 있고, 이동 시킬 수 있고, 삭제 할 수 있다. 각각의 컨테이너는 고립되어 있어며 안전한 어플리케이션 플랫폼이다.
도커 컨테이너는 도커의 실행 컴포넌트이다.

그래서 도커는 어떻게 동작하나?

  1. 어플리케이션을 담기 위해 도커이미지를 빌드 할 수 있다.
  2. 도커 이미지로 부터 어플리케이션을 실행하기 위한 도커 컨테이너를 만들수 있다.
  3. 도커 이미지는 공개/사설 저장소에 공유할 수 있다.

도커 이미지는 어떻게 동작하나?

도커 이미지는 읽기전용 템플릿이고, 이것으로 부터 도커 컨테이너들을 작동시키는 것은 위에서 알게되었다.
각각의 이미지는 연속된 레이어들로 구성되어 있다. 도커는 union file systems를 사용해서 레이어들을 하나의 이미지로 합친다.
Union file systems는 분리되어 있는 여러 파일시스템을 투명하게 덮어서 하나의 파일 시스템 형태로 만들어준다.
여러개의 레이어가 있다는 것은 도커가 가벼운 이유 중 하나이다.
예를 들어서 어플리케이션을 새로운 버전으로 변경하기 위해 도커의 이미지를 다시 빌드한다고 해보자.
그런경우에 이미지 전체를 새로 빌드하는 것이 아니라, 새로 추가된 부분 또는 업데이트 된 부분만 변경하면 된다.
그리고 배포할 경우에도 변경된 부분만 배포하면 되기 때문에 도커 이미지는 더 빠르고 더 심플하다.
모든 이미지는 우분투나 페도라 같은 베이스 이미지로 부터 시작된다. 그리고 베이스 이미지는 보통 Docker hub에서 가져오게된다.
도커 이미지는 베이스 이미지에서 인스트럭션 셋을 작성하여 만들어지게 되는데, 각각의 인스트럭션은 이미지의 새로운 레이어를 생성하게 된다.
인스트럭션은 다음과 같은 액션들을 포함한다.

  • Run 커맨드
  • 파일또는 디렉토리의 추가
  • 환경변수 설정
  • 이미지에서 컨테이너를 런칭할때 어떤 프로세스가 실행되는지

도커 레지스트리는 어떻게 동작하나?

도커 레지스트리는 도커 이미지들을 위한 스토어이다. Docker hub 같은 퍼블릭 레지스트리를 사용하거나, 자체구축을 해서 사용해도 된다.
도커클라이언트로 업로드한 이미지들을 검색할 수 있고, 땡겨 받을 수도 있다.
Docker hub에도 사설 스토리지 서비스를 해주는데, 1개는 무료이지만 그 이상은 비용이 든다. 자세한건 https://hub.docker.com/plans 링크 참고

컨테이너는 어떻게 동작하나?

컨테이너는 운영체제, 유저가 추가한 파일들 그리고 메타데이터로 구성되어 있다. 이미 봤지만, 각각의 컨테이너는 이미지로 부터 빌드된다.
이미지는 컨테이너가 올라가려면, 어떤 프로세스를 실행해야하는지 그에 따른 이런 저런 설정파일을 컨테이너에 알려준다.
컨테이너가 이미지로 부터 실행이 되어서 올라갈 때에, 이미지의 최상단에 읽기-쓰기가 되는 레이어를 더하게 된다.

당신이 컨테이너를 실행할때 무슨일이 일어나나?

docker 바이너리를 사용하건 API를 사용하건 Docker 클라이언트는 Docker 데몬에게 컨테이너를 실행시키라고 요청을 보낸다.

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

위의 커맨드를 한번 쪼개보자.
docker 커맨드로 도커 바이너리를 실행시키고, 새로운 컨테이너를 올리기위해 run 서브커맨드를 사용한다. 도커 클라이언트가 도커 데몬에게 요청을 보내기위한 최소한의 내용은 다음과 같다.

  • 컨테이너로 빌드할 도커 이미지가 무엇인가, 여기서는 ubuntu 베이스 이미지이다.
  • 컨테이너가 올라간 후 실행하고 싶은 커맨드는 무엇인가, 여기서는 /bin/bash 라는 명령어를 사용한다.

그러면 위의 명령어가 실행되면 어떤 일이 일어날까?

  • ubuntu 이미지를 밀어올린다.(Pull)
  • 새로운 컨테이너를 만든다.
  • 읽기-쓰기레이어에 파일 시스템을 할당하고 마운트한다.
  • 네트웍과 브릿지 인터페이스를 할당한다
  • 아이피를 세팅한다.
  • 당신이 지정한 프로세스를 실행한다.
  • 어플리케이션의 로그를 캡쳐한다.

도커를 지탱하는 기술(Underlying technology)

도커는 Go 언어를 사용하여 작성되었고, 몇가지 커널의 기능을 사용했다.

Namespaces

도커는 namespaces라는 워크스페이스(우리가 컨테이너라고 부르는) 격리화 기술의 이점을 차용했다. 컨테이너를 실행하게 되면, 도커는 해당컨테이너를 위한 namespaces의 셋을 생성한다.
Namespaces는 레이어의 격리를 제공한다 : 각각의 컨테이너는 그들 자신의 namespace를 가지게 되고 외부로는 접속할 수 없다.
리눅스에서 도커가 사용하는 몇가지 namespaces는 아래와 같다.

  • pid namespace : 프로세스 격리에 사용
  • net namespace : 네트워크인터페이스 관리에 사용
  • ipc namespace : IPC리소스 접근에 대한 관리에 사용 (IPC : InterProcess Communication)
  • mnt namespace : 마운트포인트의 관리에 사용
  • uts namespace : 커널격리와 버전 인식에 사용 (UTS : Unix Timesharing System)

Control groups

도커는 cgroup 또는 control groups라는 리눅스의 또다른 기술을 사용한다.
컨트롤 그룹은 도커가 CPU, 메모리, 디스크 같은 하드웨어리소스를 쉐어 할 수 있게 제어한다.

Union file systems

Union file systems또는 UnionFS라고도 하는 파일시스템은 레이어를 생성하는데 사용되고, 매우 가볍고 빠르다. 도커는 컨테이너를 위한 빌딩 블록을 제공하는데에 union file systems를 사용한다. 도커는 AUFS, btrfs, vfs, DeviceMapper 같은 Union file systems를 사용할 수 있다.

Container format

도커는 이러한 컴포넌트들을 조합하여 감싸는데 이걸 컨테이너 포맷이라고 한다. 디폴트 컨테이너 포맷은 libcontainer라고 부른다.
또한 도커는 LXC라는 전통적인 리눅스 컨테이너도 지원한다.
추후에는 BSD Jails또는 Solaris Zones를 통합해서 다른 컨테이너 포맷도 지원할 예정이다.