Contents

개인 도커 이미지 저장소 만들기

컨테이너 기반으로 서비스를 배포하는 경우가 늘어나고 있다. 공개해도 괜찮은 컨테이너들이 있지만, 서비스의 중요한 정보들을 저장하고 있는 컨테이너들은 개인 저장소에서 저장해야 한다. 대략 Dockerfile은 git으로 관리하고, 이것을 빌드(build)해서 개인 저장소에 push한 다음 배포하는 방식이 될 것이다. 나는 개인 저장소를 만들는 방법을 살펴보려 한다.

환경

전체 구성은 다음과 같다.

  • Workstation : 이미지를 빌드하는 개발 서버다. 여기에서 이미지를 빌드하고 저장소에 push 한다.
  • 저장소 : 게스트 운영체제를 만들어서 여기에 저장소를 만든다. virtualbox로 만든다.
  • 서비스 인스턴스 : 저장소로 부터 이미지를 pull해서 애플리케이션을 서비스한다. virtualbox로 만든다.
운영체제는 우분투 리눅스 14.04 LTS로 통일했다. 도커 버전은 1.9.1

python registry 설치

python(Django) 기반의 registry를 널리 사용하고 있는 것 같다. 삽질하지 않고 이걸 사용하기로 했다. 도커 이미지로 간단하게 설치 할 수 있다는게 마음에 든다. 저장소에 설치했다.
# docker run -p 5000:5000 -v /tmp/registry:/tmp/registry registry

도커 이미지 만들기

이제 Workstation으로 이동해서 간단한 웹 서버 이미지를 만든다. 아래는 테스트에 사용한 웹 서버 코드다.
package main

import (
    "fmt"
    "net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello World\n")
}
func main() {
    http.HandleFunc("/", hello)
    http.ListenAndServe(":8000", nil)
}
위 코드를 도커 이미지로 만들기 위해서 빌드 했다.
# CGO_ENABLED=0 GOOS=linux go build 
디렉토리에 webserver파일이 보일 거다. 이제 Dockerfile을 만들었다.
FROM scratch
ADD webserver /
CMD ["/webserver"]
이미지를 빌드 한다. 이미지의 이름은 webserver로 했다.
# docker build -t webserver .
Sending build context to Docker daemon  6.58 MB
Step 1 : FROM scratch
 ---> 
Step 2 : ADD webserver /
 ---> d9d3337b1d87
Removing intermediate container 70770abbe2fc
Step 3 : CMD /webserver
 ---> Running in fe907cfd5ab8
 ---> 0a7804df4ef7
Removing intermediate container fe907cfd5ab8
약 7메가 짜리 이미지가 만들어졌다. 작은 크기이지만 엄연히 웹 서버 역할을 할 수 있는 이미지다. 도커 이미지 목록을 보자.
# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
webserver           latest              0a7804df4ef7        3 minutes ago       6.563 MB
ubuntu              latest              e9ae3c220b23        3 weeks ago         187.9 MB
이미지가 제대로 작동하는지 실행해서 테스트 했다.
# docker run -it --rm webserver
# docker inspect c8dc1e7d9859 | grep IPAddress
     ....
     "IPAddress": "172.17.0.2",
# curl 172.17.0.2:8000
Hello World

저장소로 이미지를 push 하기

이제 workstation에서 개발한 webserver 이미지를 저장소로 push 해보자. 먼저 태그를 붙이고
# docker tag webserver:latest 192.168.56.50:5000/webserver
push를 하면
# docker push 192.168.56.50:5000/webserver
The push refers to a repository [192.168.56.50:5000/webserver] (len: 1)
unable to ping registry endpoint https://192.168.56.50:5000/v0/
v2 ping attempt failed with error: Get https://192.168.56.50:5000/v2/: EOF
v1 ping attempt failed with error: Get https://192.168.56.50:5000/v1/_ping: EOF
... 에러가 떨어진다. docker는 저장소의 이용에 https를 사용하는데, 앞서 설치한 registry가 https를 지원하지 않기 때문에 발생하는 문제다. 실제 http로는 서비스가 잘 되는 걸 확인 할 수 있다.
# curl http://192.168.56.50:5000
"docker-registry server"

이 문제를 해결 하기 위해서 docker 데몬이 저장소를 http로 접근하는 것을 허용 하도록 설정을 변경 했다. Workstation의 docker 설정파일을 수정하고 docker 서비스를 재 시작했다.
# cat /etc/default/docker
...
DOCKER_OPTS="--insecure-registry 192.168.56.50:5000"
...
# /etc/init.d/docker restart
# ps -ef | grep docker
root     22196     1  3 00:07 ?        00:00:00 /usr/bin/docker daemon --insecure-registry 192.168.56.50:5000

다시 push를 시도해 보자.
# docker push 192.168.56.50:5000/webserver
The push refers to a repository [192.168.56.50:5000/webserver] (len: 1)
Sending image list
Pushing repository 192.168.56.50:5000/webserver (1 tags)
d9d3337b1d87: Image successfully pushed 
0a7804df4ef7: Image successfully pushed 
Pushing tag for rev [0a7804df4ef7] on {http://192.168.56.50:5000/v1/repositories/webserver/tags/latest}

이미지 push완료. 언젠가는 https 기반으로 바꿔야 겠지만 우선은 이걸로 충분하다.

도커 이미지 pull

서비스 서버에서 저장소에 있는 webserver 이미지를 pull해서 컨테이너를 만들어 보자. 이 서버 역시 insecure-registry 설정을 해줘야 한다.
# docker pull 192.168.56.50:5000/webserver
Using default tag: latest
Pulling repository 192.168.56.50:5000/webserver
0a7804df4ef7: Download complete 
d9d3337b1d87: Download complete 
Status: Downloaded newer image for 192.168.56.50:5000/webserver:latest
# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
192.168.56.50:5000/webserver   latest              0a7804df4ef7        45 minutes ago      6.563 MB
ubuntu                         latest              91e54dfb1179        3 months ago        188.4 MB

컨테이너를 만들고 테스트해보자.
# docker run -p 8000:8000 -it --rm 192.168.56.50:5000/webserver
# curl 192.168.56.51:8000

개발 프로세스 만들기

컨테이너를 배포한다는 것은 소프트웨어를 배포하는 것과 마찬가지다. 소프트웨어의 가동을 위해서 필요한 환경과 자원들을 패키지로 묶어서 배포 할 수 있다는 것에 약간의 차이가 있을 뿐이다. 본질은 소프트웨어의 배포다. 따라서 컨테이너도 소프트웨어의 개발 & 배포 프로세스에 통합돼야 한다.

컨테이너는 소프트웨어를 담는 그릇이다.

도커 이미지와 컨테이너의 버전을 어떻게 관리해야 할까 ? 이런 관점에서 보면, 개발과 배포의 과정이 굉장히 복잡해 진다. 소프트웨어 버전 관리하는 것도 복잡한데, 여기에 이미지 버전까지 관리를 해야 한다고 생각해 보라.

복잡하게 생각 할 필요가 없다. 컨테이너는 소프트웨어를 담는 그릇일 뿐이다.

git을 이용해서 코드를 관리하고 있다고 가정해 보자. 코드는 dev - qa - operation 의 과정을 거쳐서 배포된다. 코드의 흐름을 관리하기 위해서 (git flow 보다 단순한)github flow를 사용하고 있다. 이 경우 코드는 아래와 같이 관리 될 것이다.

... 계속...