이재홍의 언제나 최신 Docker - Unit 6. Docker 좀더 활용하기

저작권 안내
  • 책 또는 웹사이트의 내용을 복제하여 다른 곳에 게시하는 것을 금지합니다.
  • 책 또는 웹사이트의 내용을 발췌, 요약하여 강의 자료, 발표 자료, 블로그 포스팅 등으로 만드는 것을 금지합니다.

Docker 좀더 활용하기

이재홍 http://www.pyrasis.com

지금까지 Docker 명령의 기본 사용 방법을 알아보았습니다. 이번 장에서는 좀더 다양한 활용 방법을 알아보겠습니다.

Docker 개인 저장소 구축하기

Docker 명령은 기본적으로 Docker Hub를 사용합니다. 이번에는 나만의 저장소 서버를 구축해보겠습니다.

Docker 저장소 서버는 Docker 레지스트리(registry) 서버라고 부릅니다. docker push 명령으로 레지스트리 서버에 이미지를 올리고, docker pull 명령으로 이미지를 받을 수 있습니다.

Docker 레지스트리 서버에서 이미지 데이터를 저장하는 방법은 매우 다양합니다. 그중에서 Docker 레지스트리가 동작하는 서버에 저장하는 방법과 Amazon S3에 저장하는 방법을 설명하겠습니다.

먼저 기존에 실행되고 있는 Docker 데몬을 정지한 뒤 --insecure-registry 옵션을 사용하여 Docker 데몬을 실행합니다.

$ sudo systemctl stop docker.socket
$ sudo systemctl stop docker
$ sudo dockerd --insecure-registry localhost:5000

보통 Docker 데몬을 직접 실행하지 않고 서비스 형태로 실행합니다. 이때는 /etc/docker/daemon.json 파일을 생성하고 다음과 같이 저장합니다(이 파일은 root 권한으로 수정해야 합니다).

/etc/docker/daemon.json
{
  "insecure-registries": ["localhost:5000"]
}

/etc/docker/daemon.json 파일을 수정했으면 Docker 서비스를 재시작합니다.

$ sudo systemctl restart docker

로컬에 이미지 데이터 저장

Docker 레지스트리 서버도 Docker Hub를 통해 Docker 이미지로 제공됩니다. 먼저 Docker 레지스트리 이미지를 받습니다.

$ sudo docker pull registry:latest

registry:latest 이미지를 컨테이너로 실행합니다.

$ sudo docker run -d -p 5000:5000 --name hello-registry \
    -v /tmp/registry:/tmp/registry \
    registry

이렇게 실행하면 이미지 파일은 호스트의 /tmp/registry 디렉터리에 저장됩니다.

그림 6-1 Docker 레지스트리, 로컬에 이미지 데이터 저장

push 명령으로 이미지 올리기

앞에서 만든 hello:0.1 이미지를 개인 저장소에 올려보겠습니다.

$ sudo docker tag hello:0.1 localhost:5000/hello:0.1
$ sudo docker push localhost:5000/hello:0.1

태그를 생성하는 명령은 docker tag <이미지 이름>:<태그> <Docker 레지스트리 URL>/<이미지 이름>:<태그> 형식입니다.

이미지를 올리는 명령은 docker push <Docker 레지스트리 URL>/<이미지 이름>:<태그> 형식입니다.

개인 저장소에 이미지를 올릴 때는 태그를 먼저 생성해야 합니다. docker tag 명령으로 hello:0.1 이미지를 localhost:5000/hello:0.1 태그로 생성합니다. 그리고 docker push 명령으로 localhost:5000/hello:0.1 이미지를 개인 저장소에 올립니다(태그를 생성했으므로 실제로는 hello:0.1 이미지가 올라갑니다).

이제 다른 서버에서 개인 저장소(Docker 레지스트리 서버)에 접속하여 이미지를 받아올 수 있습니다. 개인 저장소 서버 IP 주소가 172.31.23.145라면 다음과 같이 명령을 실행합니다.

$ sudo docker pull 172.31.23.145:5000/hello:0.1

참고로 명령을 실행하려면 /etc/docker/daemon.json 파일에서 insecure-registries172.31.23.145:5000이 들어있어야 합니다. 그리고 Docker 서비스를 재시작하는 것을 잊지마세요.

/etc/docker/daemon.json
{
  "insecure-registries": ["localhost:5000", "172.31.23.145:5000"]
}

이미지 목록을 출력합니다.

$ sudo docker images
REPOSITORY                 TAG       IMAGE ID       CREATED          SIZE
hello                      0.2       011ff3ff87e9   29 minutes ago   170MB
172.31.23.145:5000/hello   0.1       8307ff628ec8   35 minutes ago   170MB
hello                      0.1       8307ff628ec8   35 minutes ago   170MB
localhost:5000/hello       0.1       8307ff628ec8   35 minutes ago   170MB
mongo                      latest    d34d21a9eb5b   7 days ago       693MB
ubuntu                     22.04     2dc39ba059dc   7 days ago       77.8MB
nginx                      latest    2b7d6430f78d   2 weeks ago      142MB
registry                   latest    3a0f7b0a13ef   4 weeks ago      24.1MB

개인 저장소에서 172.31.23.145:5000/hello 이미지를 받았습니다.

이미지를 삭제할 때에는 아래와 같이 실행합니다.

$ sudo docker rmi 172.31.23.145:5000/hello:0.1

Amazon S3에 이미지 데이터 저장

이번에는 AWS의 S3에 이미지 데이터를 저장하는 방법입니다.

먼저 앞에서 생성한 hello-registry 컨테이너를 정지합니다.

$ sudo docker stop hello-registry

Docker 레지스트리 이미지를 받습니다.

$ sudo docker pull registry:latest

registry:latest 이미지를 컨테이너로 실행합니다.

$ sudo docker run -d -p 5000:5000 --name s3-registry \
   -e REGISTRY_STORAGE=s3 \
   -e REGISTRY_STORAGE_S3_BUCKET=examplebucket10 \
   -e REGISTRY_STORAGE_S3_REGION=ap-northeast-2 \
   -e REGISTRY_STORAGE_S3_ACCESSKEY=AKIABCDEFGHIJKLMNOPQ \
   -e REGISTRY_STORAGE_S3_SECRETKEY=sF4321ABCDEFGHIJKLMNOPqrstuvwxyz21345Afc \
   registry

S3를 사용하려면 -e 옵션으로 설정을 해주어야 합니다.

  • REGISTRY_STORAGE: s3을 설정합니다.
  • REGISTRY_STORAGE_S3_BUCKET: 이미지 데이터를 저장할 S3 버킷 이름입니다. 예제에서는 examplebucket10을 설정했습니다. 여러분이 생성한 S3 버킷 이름을 입력합니다.
  • REGISTRY_STORAGE_S3_REGION: S3 버킷의 리전을 설정합니다.
  • REGISTRY_STORAGE_S3_ACCESSKEY: AWS 액세스 키를 설정합니다.
  • REGISTRY_STORAGE_S3_SECRETKEY: AWS 시크릿 키를 설정합니다.

이제 s3-registry 저장소에 Docker 이미지를 push하면 S3 버킷에 저장됩니다.

그림 6-2 Docker 레지스트리, Amazon S3에 이미지 데이터 저장

기본 인증 사용하기

Docker 레지스트리에는 로그인 기능이 없습니다. 따라서 Nginx의 기본 인증(Basic Authentication) 기능을 사용해야 합니다. 또한, HTTP 프로토콜에서는 인증을 지원하지 않으므로 반드시 HTTPS 프로토콜을 사용해야 합니다.

먼저 /etc/hosts 파일을 편집하여 테스트용 도메인을 추가합니다. 이 파일은 root 권한으로 수정해야 합니다. 도메인을 구입하지 않았을 때는 이 부분을 반드시 설정해주어야 하며, 도메인을 구입하여 DNS를 설정했다면 이 부분은 건너뛰어도 됩니다.

/etc/hosts
127.0.0.1 localhost
<레지스트리 서버 IP 주소> registry.example.com

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

여러분의 레지스트리 서버 IP 주소를 registry.example.com으로 설정합니다. 이 문서에서는 registry.example.com을 기준으로 설명하겠습니다.

이제 SSL 사설 인증서(Self Signed)를 생성하겠습니다. SSL 공인 인증서를 구입했다면 이 부분은 건너뛰어도 됩니다.

  • /CN: Docker 레지스트리를 실행하는 서버의 도메인입니다. 이 부분을 정확하게 입력하지 않으면 인증서를 사용해도 로그인할 때 에러가 발생합니다. /etc/hosts 파일에 설정한대로 registry.example.com를 입력합니다.
  • subjectAltName: SAN입니다. subjectAltName=DNS:registry.example.com를 입력합니다.
$ mkdir certs
$ cd certs
~/certs$ openssl genrsa -out ca.key 2048
~/certs$ openssl req -new -x509 -days 365 -key ca.key \
    -subj "/C=CN/ST=GD/L=SZ/O=Acme, Inc./CN=Acme Root CA" \
    -out ca.crt
~/certs$ openssl req -newkey rsa:2048 \
    -nodes -keyout server.key \
    -subj "/C=CN/ST=GD/L=SZ/O=Acme, Inc./CN=registry.example.com" -out server.csr
~/certs$ openssl x509 -req \
    -extfile <(printf "subjectAltName=DNS:registry.example.com") \
    -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
$ cd ..

이제 server.crt 인증서 파일을 시스템에 설치를 해주어야 합니다(인증서 파일을 설치하지 않으려면 --insecure-registry 옵션을 사용해야 합니다. 이 부분은 뒤에 따로 설명하겠습니다).

$ sudo mkdir -p /etc/docker/certs.d/registry.example.com
$ sudo cp certs/ca.crt /etc/docker/certs.d/registry.example.com/ca.crt

/etc/hosts에 도메인을 추가하고, 인증서 파일을 설치했으면 Docker 서비스를 재시작합니다. Docker 서비스를 재시작해야 추가된 도메인과 설치된 인증서가 적용됩니다.

$ sudo systemctl restart docker

Docker 레지스트리에 접속할 다른 시스템에도 server.crt 인증서 파일을 복사하여 같은 방식으로 설치를 하고 Docker 서비스를 재시작합니다. 그리고 도메인을 구입하지 않았다면 /etc/hosts에 레지스트리 서버(registry.example.com)의 IP 주소를 설정합니다.

--insecure-registry 옵션
server.crt 인증서 파일을 시스템에 설치하지 않으려면 Docker 데몬을 실행할 때 --insecure-registry 옵션을 사용해야 합니다.

$ sudo dockerd --insecure-registry registry.example.com
  • --insecure-registry 옵션에 Docker 레지스트리의 도메인을 설정합니다. 도메인 여러 개를 설정하려면 --insecure-registry 옵션을 여러 번 사용하면 됩니다.

보통 Docker 데몬을 직접 실행하지 않고 서비스 형태로 실행합니다. 이때는 /etc/docker/daemon.json 파일의 insecure-registries 부분을 다음과 같이 설정합니다(이 파일은 root 권한으로 수정해야 합니다).

/etc/docker/daemon.json
{
  "insecure-registries": ["registry.example.com"]
}

/etc/docker/daemon.json 파일을 수정했으면 Docker 서비스를 재시작합니다.

$ sudo systemctl restart docker

Docker 레지스트리에 접속할 다른 시스템에도 같은 방식으로 --insecure-registry 옵션을 사용하여 Docker 데몬을 실행합니다.

이제 사용자 계정과 비밀번호를 저장할 htpasswd 파일을 생성해야 합니다.

다음과 같이 auth/htpasswd 파일을 생성하고 hellouser라는 예제 사용자를 추가합니다. 비밀번호 입력 부분에는 사용할 비빌번호를 입력합니다.

$ mkdir auth
$ sudo docker run --entrypoint htpasswd --rm httpd:2 -Bbn hellouser hellopassword > auth/htpasswd

다음 명령을 실행하여 Docker 레지스트리 컨테이너를 생성합니다.

$ sudo docker run -d \
  --name registry \
  -v "$(pwd)"/auth:/auth \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -v "$(pwd)"/certs:/certs \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/server.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/server.key \
  -p 443:443 \
  registry:2
  • -v 옵션으로 auth, certs 디렉터리를 컨테이너의 /auth, /certs로 연결합니다.
  • REGISTRY_AUTH_HTPASSWD_PATH: 앞에서 생성한 htpasswd 파일을 설정합니다.
  • REGISTRY_HTTP_TLS_CERTIFICATE, REGISTRY_HTTP_TLS_KEY: 앞에서 생성한 server.key, server.crt 파일을 설정합니다.

docker login 명령으로 https://registry.example.com에 로그인합니다. Username과 Password에는 htpasswd 명령으로 생성한 사용자(hellouser)와 비밀번호(hellopassword)를 입력합니다.

$ sudo docker login https://registry.example.com
Username: hellouser
Password: hellopassword
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

docker login <Docker 레지스트리 URL> 형식입니다.

주의
도메인 설정이 귀찮다고 그냥 건너뛰고 IP 주소만 사용하면 로그인이 안 됩니다. 인증서에 설정한 도메인과 docker login 명령에 입력한 도메인이 반드시 일치해야 합니다. HTTPS 프로토콜은 IP 주소 접속을 허용하지 않으므로 구입하지 않은 도메인은 /etc/hosts 파일에 등록하여 사용합니다.

이제 앞에서 만든 hello:0.1 이미지를 개인 저장소에 올려보겠습니다.

$ sudo docker tag hello:0.1 registry.example.com/hello:0.1
$ sudo docker push registry.example.com/hello:0.1
The push refers to repository [registry.example.com/hello]
3fc4e1f2a517: Pushed
4d3d2ac7a313: Pushed
11fb43ff38a5: Pushed
7e6bc37fff8b: Pushed
7f5cbd8cc787: Pushed
0.1: digest: sha256:6b67420328f3527e518eccced8c24ac90e699b022545610f6e18bf873856eb8f size: 1367

이미지의 태그는 <Docker 레지스트리 URL>/<이미지 이름>:<태그> 형식으로 생성합니다. 우리는 registry.example.com으로 설정했으므로 registry.example.com/hello:0.1이 됩니다.

다른 서버에서는 다음 명령을 실행하여 registry.example.com에 저장된 이미지를 받을 수 있습니다.

$ sudo docker pull registry.example.com/hello:0.1

저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

2022-10-03