はじめに
基本的には、公式ドキュメント通りに進めば行けるのですが、
Basic認証でハマったので、一通り手順を公開します。
環境
- Docker version 1.9.1
- docker-compose version 1.5.2
構成
下がファイル郡の構成となります。
+ registry
+ auth
- htpasswd
+ certs
- domain.crt
- domain.key
- docker-compose.yml
サーバ側は192.168.33.40でdocker registryを起動して、
そこに対して各サーバからイメージの送信・取得を行っていきます。
docker registry
[192.168.33.20] <---> [192.168.33.40]
docker push/pull
オレオレ証明書作成
Docker Registryは通信の際にHTTPSを使用するので、証明書を作成します。
個人で使用するので自己証明書で代用します。
Country Nameなど入力項目がありますが、ほぼ空で大丈夫です。
Common Nameの箇所だけサーバのIPかドメインなどを入れてやります。
$ mkdir -p certs
$ openssl req \
> -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
> -x509 -days 365 -out certs/domain.crt
Generating a 4096 bit RSA private key
..........................+++
................................+++
unable to write 'random state'
writing new private key to 'domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:192.168.33.40
Email Address []:
証明書を作業用サーバに保存
作成した証明書を作業用サーバに保存してやります。
$ sudo mkdir -p /etc/docker/certs.d/192.168.33.40:5000
$ cd /etc/docker/certs.d/192.168.33.40:5000/
$ scp core@192.168.33.40:/path/to/certs/domain.crt ./ca.crt
これをしておかないと、bad certificate となってしまいます。
$ docker login 192.168.33.40:5000
Error response from daemon: invalid registry endpoint https://192.168.33.40:5000/v0/: unable to ping registry endpoint https://192.168.33.40:5000/v0/
v2 ping attempt failed with error: Get https://192.168.33.40:5000/v2/: dial tcp 192.168.33.40:5000: i/o timeout
v1 ping attempt failed with error: Get https://192.168.33.40:5000/v1/_ping: dial tcp 192.168.33.40:5000: i/o timeout. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry 192.168.33.40:5000` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/192.168.33.40:5000/ca.crt
Basic認証用ファイル作成
以下のコマンドでhtpasswdファイルを作成します。
$ htpasswd -Bbn suzuki password > auth/htpasswd
この際オプションに注意!必ず -B オプションを付けてBcryptを利用して暗号化するようにします。
これを付けてやらないと以下の様にdocker loginコマンド実行時に認証エラーとなってしまいます。
[masa@localhost]% docker login 192.168.33.40:5000
Username: suzuki
Password:
Email:
Error response from daemon: no successful auth challenge for https://192.168.33.40:5000/v2/ - errors: [basic auth attempt to https://192.168.33.40:5000/v2/ realm "Registry Realm" failed with status: 401 Unauthorized]
docker-compose
毎回docker runでオプション付けて起動するのは面倒なので、
docker-composeを使用してやります。
volumesの項目のパスは適宜変更してやります。
registry:
restart: always
image: registry:2
ports:
- 5000:5000
environment:
REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
REGISTRY_HTTP_TLS_KEY: /certs/domain.key
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
volumes:
- /path/to/registry/data:/var/lib/registry
- /path/to/registry/certs:/certs
- /path/to/registry/auth:/auth
Registry起動
ではコンテナリポジトリを起動します。
[192.168.33.40]$ docker-compose up -d
起動したら、作業用サーバでログインしてます。
[192.168.33.20]$ docker login 192.168.33.40:5000
Username: suzuki
Password:
Email:
WARNING: login credentials saved in /home/suzuki/.docker/config.json
Login Succeeded
ログインに成功したので、イメージを送信してみます。
[192.168.33.20]$ docker pull busybox
[192.168.33.20]$ docker tag busybox 192.168.33.40:5000/test
[192.168.33.20]$ docker rmi 192.168.33.40:5000/test
[192.168.33.20]$ docker pull 192.168.33.40:5000/test
ログインに失敗する場合
ここまでで docker login に失敗してしまう場合は以下をお試し下さい。
OSレベルでの証明書をセット
以下のドキュメントを参考に各OSに設定して下さい。
ここではCentOS7での例を実行しています。
Configuring Docker Trusted Registry
https://docs.docker.com/docker-trusted-registry/configuration/
[192.168.33.20]$ cp certs/domain.crt /etc/pki/ca-trust/source/anchors/192.168.33.40.crt
[192.168.33.20]$ update-ca-trust enable
[192.168.33.20]$ update-ca-trust
[192.168.33.20]$ systemctl restart docker
証明作成時にsubjectAltNameを付ける
[192.168.33.20]$ vi /etc/pki/tls/openssl.conf
[ v3_ca ]
subjectAltName = IP:192.168.33.40
[192.168.33.20]$ openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
-x509 -days 365 -out certs/domain.crt
[192.168.33.20]$ cp certs/domain.crt /etc/docker/192.168.33.40:5000/ca.crt
[192.168.33.20]$ systemctl restart docker
作成した証明書は registry を起動するサーバにもコピーします。
おわりに
個人用にプライベートなコンテナリポジトリが気軽に手入ります。
本格的な運用の際にはAmazon EC2 Container Registryなどを使用するのが管理が楽ですね。
参考
- Configuring Docker Trusted Registry
https://docs.docker.com/docker-trusted-registry/configuration/ - Insecure Registry
https://docs.docker.com/registry/insecure/ - Failed tls handshake. Does not contain any IP SANs
http://serverfault.com/questions/611120/failed-tls-handshake-does-not-contain-any-ip-sans