---
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 <nexus>
	(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
<!-- ... -->
  <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
    <Set name="KeyStorePath"><Property name="ssl.etc"/>/keystore.jks</Set>
    <!-- Change -->
    <Set name="KeyStorePassword">foo</Set>
    <!-- Change -->
    <Set name="KeyManagerPassword">foo</Set>
    <!-- ... -->
  </New>
<!-- ... -->
```

```
/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ライフが送れる ✈️
