--- title: Nexus RepositoryのDocker Registryを使ってオフラインでConcourse CIを使う tags: ["Concourse CI", "Docker", "Docker Registry", "Nexus Repository"] categories: ["Dev", "CI", "ConcourseCI"] date: 2016-12-08T16:22:15Z updated: 2016-12-08T16:22:15Z --- PrivateなネットワークでConcourse CIを立てたくてDocker Registryを置いたときの設定メモ。 Docker Registryは公式のものではなくて、[Nexus Repository OSS](https://www.sonatype.com/docker)を使った。理由としては、Concourse CIでビルドするアプリがMavenを使っているので、Mavenレポジトリも立てる必要があり、Nexusは両方を含んでいたから。同じようなプロダクトにはJFrogのArtifactoryにがあるけど、Artifactoryは[OSS版にDocker Registryが含まれていない](https://www.sonatype.com/download-nexus-repository-trial)。とりあえず、検証したかったのでNexus Repository OSSを選んだ。(Artifactory好きなら、Artifactory Pro買ってもいいと思う) 今回は、Docker Registry(とMaven Repository)のあるサーバーからはインターネットにアクセスしていいけど、Concourse CIのあるネットワーク(BOSHでインストール)からインターネットにアクセスできないという環境なので、PublicなDockerイメージを取ってくるのにProxyサーバーを用意すれば良い。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/aa58024b-2323-4251-4d49-07ecbd5f68e7.png) ### Nexusのインストール [ドキュメント](https://books.sonatype.com/nexus-book/3.1/reference/install.html)の通り。 Ubuntu 16.04でインストールした。 ``` sudo apt-get install -y openjdk-8-jdk-headless sudo mkdir /opt sudo chown -R `whoami`:`whoami` /opt cd /opt wget http://download.sonatype.com/nexus/3/latest-unix.tar.gz tar xzvf latest-unix.tar.gz mv nexus-3.1.0-04 nexus ``` #### HTTPSの有効化 Docker RegistryはHTTPS推奨なので、HTTPSコネクタの設定をしておく。 [ドキュメント](https://books.sonatype.com/nexus-book/3.1/reference/security.html#ssl-inbound)の通り。 Keystoreを設定。 ``` console $ cd /opt/nexus/etc/ssl $ keytool -keystore keystore.jks -alias nexus -genkey -keyalg RSA -sigalg SHA256withRSA Enter keystore password: hoge Re-enter new password: hoge What is your first and last name? \[Unknown]: repo.example.com What is the name of your organizational unit? \[Unknown]: foo What is the name of your organization? \[Unknown]: dev What is the name of your City or Locality? \[Unknown]: Adachi-ku What is the name of your State or Province? \[Unknown]: Tokyo What is the two-letter country code for this unit? \[Unknown]: JP Is CN=repo.example.com, OU=foo, O=dev, L=Adachi-ku, ST=Tokyo, C=JP correct? \[no]: yes Enter key password for (RETURN if same as keystore password): ``` `/opt/nexus/etc/nexus-default.properties`に`application-port-ssl`を設定して、`nexus-args`に`${jetty.etc}/jetty-https.xml`を追加。 ``` properties # Jetty section application-port=8081 ##### add application-port-ssl application-port-ssl=8443 application-host=0.0.0.0 ##### add ,${jetty.etc}/jetty-https.xml nexus-args=${jetty.etc}/jetty.xml,${jetty.etc}/jetty-http.xml,${jetty.etc}/jetty-https.xml,${jetty.etc}/jetty-requestlog.xml nexus-context-path=/ # Nexus section nexus-edition=nexus-pro-edition nexus-features=\ nexus-pro-feature ``` `/opt/nexus/etc/jetty/jetty-https.xml`にKeystoreのパスワードを設定。とりあえず生で。 ``` xml /keystore.jks foo foo ``` ``` /opt/nexus/bin/nexus start ``` で実行。起動に少し時間がかかる。 `/opt/sonatype-work/nexus3/log/nexus.log`に次のログが出ていれば起動成功。 ``` console 2016-12-07 02:08:11,530+0900 INFO [jetty-main-1] *SYSTEM org.eclipse.jetty.server.ServerConnector - Started ServerConnector@4ad403e3{HTTP/1.1,[http/1.1]}{0.0.0.0:8081} 2016-12-07 02:08:11,554+0900 INFO [jetty-main-1] *SYSTEM org.eclipse.jetty.util.ssl.SslContextFactory - x509=X509@6ab9b13e(nexus,h=[repo.example.com],w=[]) for SslContextFactory@987c91(file:///opt/nexus/etc/ssl/keystore.jks,file:///opt/nexus/etc/ssl/keystore.jks) 2016-12-07 02:08:11,769+0900 INFO [jetty-main-1] *SYSTEM org.eclipse.jetty.server.ServerConnector - Started ServerConnector@430beed0{SSL,[ssl, http/1.1]}{0.0.0.0:8443} 2016-12-07 02:08:11,769+0900 INFO [jetty-main-1] *SYSTEM org.eclipse.jetty.server.Server - Started @205803ms 2016-12-07 02:08:11,770+0900 INFO [jetty-main-1] *SYSTEM org.sonatype.nexus.bootstrap.jetty.JettyServer - ------------------------------------------------- Started Sonatype Nexus OSS 3.1.0-04 ------------------------------------------------- ``` `https://[nexusサーバーのホスト名]:8443`でアクセスできる。右上の"Sign in"でログイン。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/414d1025-355f-7e9a-44ed-44d5000afb12.png) デフォルトのユーザーは`admin`/`admin123`. ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/20db80c5-830c-e2bf-e7b9-bf221f26700d.png) ### Docker HubのProxyサーバー作成 プライベートネットワークからDocker Hubで管理されているイメージを取得できるように、Proxyサーバーを作成する。ログイン後にヘッダーバー出てくる歯車アイコンをクリックして、"Repositories"を選択。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/9ddb2669-ea38-8808-2d61-30fd64595f3c.png) "Create Repository"をクリック。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/513640fd-c746-517a-22b0-30c2567c7cf1.png) "docker (proxy)"を選択。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/a9096be4-84c6-0af3-0096-86e62077fcb8.png) フォームに次の値を記入。 * Name: docker-hub * Remote storage: https://registry-1.docker.io * Docker Index: Use Docker Hub ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/ec027d69-d20b-ef11-c809-09cabae52241.png) "Create Repository"ボタンをクリックして作成。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/5fddf773-a68c-a643-a2ff-3e1df2ed71de.png) Docker Registryの集約グループを作成する。後でPrivate Hosted Registryを作成したときとか、他のRegistryのProxyを作ったときに同じURLで透過的にアクセスできるように。 再び"Create Repository"をクリックして、今度は"docker (group)"を選択。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/cb1ab8a2-a385-8530-9661-b6d3a7cc242b.png) フォームに次の値を記入。 * Name: docker-all * HTTPS: 18443 * Member repositories: docker-hub ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/6d5b72e6-67f6-37e9-9694-edae70d61c4b.png) "Create Repository"ボタンをクリックして作成。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/7cca584c-fe48-7537-2872-3f51978e6d16.png) これで`https://[nexusサーバーのホスト名]:18443`にPrivate Docker Registryが立ち上がった。 以下のコマンドで疎通確認。 ``` $ curl -v -k https://repo.example.com:18443/v2/_catalog > GET /v2/_catalog HTTP/1.1 > Host: repo.example.com:18443 > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 200 OK < Date: Tue, 06 Dec 2016 17:31:54 GMT < Server: Nexus/3.1.0-04 (OSS) < X-Frame-Options: SAMEORIGIN < X-Content-Type-Options: nosniff < Docker-Distribution-Api-Version: registry/2.0 < Content-Type: application/json < Content-Length: 19 < {"repositories":[]} ``` ### `docker`コマンドでPrivate Registryにアクセス やってもやらなくてもいいけど、`docker`コマンドでこのDocker Registryを触ってみる。 オレオレ証明書を使っているので、Insecure Registriesの設定が必要だが、この設定方法はOSによって違う。Docker for Macの場合は、Preferencesから次のような設定して"Apply & Restart"が必要。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/a2c21410-ae0a-d0cd-0b5f-fd2507eeed5f.png) `alpine`イメージをProxy経由でpullしてみる。 ``` $ docker login repo.example.com:18443 Username: admin Password: Login Succeeded $ docker pull repo.example.com:18443/alpine Using default tag: latest latest: Pulling from alpine Digest: sha256:1354db23ff5478120c980eca1611a51c9f2b88b61f24283ee8200bf9a54f2e5c Status: Downloaded newer image for repo.example.com:18443/alpine:latest $ docker images | grep example.com repo.example.com:18443/alpine latest baa5d63471ea 6 weeks ago 4.803 MB ``` Nexusの管理画面で箱のアイコンをクリック。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/ad4f923c-368b-e63e-f6e5-a3636cf5a7e3.png) "Components"をクリック。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/8d66aab2-856d-7344-c151-e72f80f9076b.png) "docker-hub"をクリック。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/863701c1-4384-7fce-ed02-e6ceb0d6ce8f.png) `library/alpine`がいることを確認。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/4b62bbb4-97f0-bb8d-7cc6-1fc0f9ddcdcb.png) ### Concourse CIでPrivate Docker Registryを使う ようやく本題。Concourse CIでPrivate Docker Registryを使うには、パイプラインのYAMLにPrivate Registryの設定を追加すれば良い。 最も簡単なパイプラインである、次の`hello.yml`を例に説明する。次の例はPrivate Docker Registryを使いっていない普通のパイプライン。 ``` yaml jobs: - name: hello-world plan: - task: say-hello config: platform: linux image_resource: type: docker-image source: repository: ubuntu tag: latest run: path: bash args: - -c - | echo "Hello World!" ``` これをPrivate Docker Registryにアクセスするようには次のようにイメージ名にRegistry情報を追加して、Nexusのアカウント情報も追加すれば良い。`insecure_registries`の設定も必要な点に注意。 ``` yaml jobs: - name: hello-world plan: - task: say-hello config: platform: linux image_resource: type: docker-image source: repository: repo.example.com:18443/ubuntu tag: latest insecure_registries: - repo.example.com:18443 username: {{nexus-username}} password: {{nexus-password}} run: path: bash args: - -c - | echo "Hello World!" ``` Nexusのアカウント情報は`credentials.yml`に外だしするのが良い。 ``` yaml nexus-username: admin nexus-password: admin123 ``` あとは次のようにパイプラインをセットすればOK ``` $ fly -t main sp -p hello -c hello.yml -l credentials.yml -n dev $ fly -t main up -p hello $ fly -t main tj -j hello/hello-world -w started hello/hello-world #1 initializing Login Succeeded Pulling repo.example.com:18443/ubuntu@sha256:3b64c309deae7ab0f7dbdd42b6b326261ccd6261da5d88396439353162703fb5... sha256:3b64c309deae7ab0f7dbdd42b6b326261ccd6261da5d88396439353162703fb5: Pulling from ubuntu af49a5ceb2a5: Pulling fs layer 8f9757b472e7: Pulling fs layer e931b117db38: Pulling fs layer 47b5e16c0811: Pulling fs layer 9332eaf1a55b: Pulling fs layer 47b5e16c0811: Waiting 9332eaf1a55b: Waiting e931b117db38: Verifying Checksum e931b117db38: Download complete 8f9757b472e7: Download complete 47b5e16c0811: Download complete 9332eaf1a55b: Download complete af49a5ceb2a5: Verifying Checksum af49a5ceb2a5: Download complete af49a5ceb2a5: Pull complete 8f9757b472e7: Pull complete e931b117db38: Pull complete 47b5e16c0811: Pull complete 9332eaf1a55b: Pull complete Digest: sha256:3b64c309deae7ab0f7dbdd42b6b326261ccd6261da5d88396439353162703fb5 Status: Downloaded newer image for repo.example.com:18443/ubuntu@sha256:3b64c309deae7ab0f7dbdd42b6b326261ccd6261da5d88396439353162703fb5 Successfully pulled repo.example.com:18443/ubuntu@sha256:3b64c309deae7ab0f7dbdd42b6b326261ccd6261da5d88396439353162703fb5. running bash -c echo "Hello World!" Hello World! succeeded ``` できた。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/522e6c9d-4ed1-fcf7-44c8-30118af9ddce.png) ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/f7d52729-b812-d6ea-3524-cfe3e54cf5c4.png) https://github.com/pivotalservices/concourse-pipeline-samples/tree/master/private-docker-registry も参考にした。 ### Private Docker Registryを作成 ここまでの例はPublicなDockerイメージをPrivateな環境で使う例でしたが、PrivateなDockerイメージを扱いたい場合は、Private Registryが必要。 再び"Create Repository"をクリックして、今度は"docker (hosted)"を選択。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/880bf704-6150-99ae-c4a8-2ff76f3849da.png) フォームに次の値を記入。 * Name: docker-private * HTTPS: 28443 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/ff47c865-9703-36de-689a-12aecafa61c1.png) "Create repository"ボタンをクリックして作成。 docker-allの方にこのdocker-privateも追加しておく。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/0098b334-c1c4-7caf-187b-ad2578dfa96a.png) Docker for Macからdocker-privateにpushするにはinsecure registriesを追加する必要がある。 ![image](https://qiita-image-store.s3.amazonaws.com/0/1852/2ee5d3cd-5bfa-b8fb-4f10-94ab3baec5a3.png) あとは次のように`https://[nexusサーバーのホスト名]:28443`にログインすればdocker-privaterイメージをpushできる。 ``` $ docker login repo.example.com:28443 Username: admin Password: Login Succeeded $ docker build . -t repo.example.com:28443/foo/bar $ docker push repo.example.com:28443/foo/bar ``` pullする方は、docker-allを見れば良いので、`https://[nexusサーバーのホスト名]:18443`のままでOK。 --- これで不自由なネットワーク内でもそこそこ快適なConcourse CIライフが送れる ✈️