以下のような Docker イメージを管理できる環境を構築してみる。
Distribution とは
Distribution は Docker イメージを管理するツールである。これを使うとセルフホスティングで Docker イメージを管理できる。
昔は Registry という名前だったが、別の機関に移管され、名前が変わったらしい。
Distribution の Docker イメージ名がregistryだったり所々にその名残りが見受けられるが、Distribution のことなんだなと思えば良い。
Distribution をデプロイする
Docker Compose で Distribution をデプロイしてみる。
以下のようなdocker-compose.ymlを作成する。
services:
  registry:
    image: registry:latest
    ports:
      - 8090:5000
    volumes:
      - ./distribution/registry:/var/lib/registry
    restart: always
  registry-ui:
    image: joxit/docker-registry-ui:main
    restart: always
    ports:
      - 8091:80
    environment:
      - SINGLE_REGISTRY=true
      - REGISTRY_TITLE=Docker Registry UI
      - DELETE_IMAGES=true
      - SHOW_CONTENT_DIGEST=true
      - NGINX_PROXY_PASS_URL=http://registry:5000
      - SHOW_CATALOG_NB_TAGS=true
      - CATALOG_MIN_BRANCHES=1
      - CATALOG_MAX_BRANCHES=1
      - TAGLIST_PAGE_SIZE=100
      - REGISTRY_SECURED=false
      - CATALOG_ELEMENTS_LIMIT=1000
Distribution は画面を持たず動作確認が大変なので、Docker Registry User Interface も同時に導入している。
ポートは 8090 と 8091 に割り当てているが、好きに変えて良い。
以下のコマンドを実行し、コンテナを起動する。
$ docker compose up
Docker Registry UI (http://localhost:8091)にアクセスして、以下のような画面が表示されていれば良い。
Docker イメージを作成する
Distribution に登録する Docker イメージを作成する。既に手元に登録したい Docker イメージがある場合、この手順を無視して良い。
Docker で動く Next.js アプリケーションを作ってみる。
$ npx create-next-app@latest
適当に答える。
✔ What is your project named? … nextjs-example
✔ Would you like to use TypeScript? … No / Yes
✔ Which linter would you like to use? › ESLint
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack? (recommended) … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
Creating a new Next.js app in /path/to/nextjs-example.
以下のコマンドを実行し、アプリケーションが動作することを確認する。
$ npm run dev
プロジェクトにDockerfileと.dockerignoreを追加する。
 .
+├── .dockerignore
+├── Dockerfile
 ├── README.md
 ├── eslint.config.mjs
 ├── next-env.d.ts
 ├── next.config.ts
 ├── package-lock.json
 ├── package.json
 ├── public
 ├── src
 └── tsconfig.json
# ビルド環境に必要なパッケージを用意したステージ
FROM node:22.19.0 AS development-dependencies-env
# ファイルをコピーする
WORKDIR /app
COPY . /app
# パッケージをインストールする
RUN npm ci
# ビルドする
RUN npm run build
# プロダクション環境に必要なパッケージだけを用意したステージ
FROM node:22.19.0 AS production-dependencies-env
WORKDIR /app
COPY ./package.json ./package-lock.json /app
RUN npm ci --omit=dev
# プロダクションステージ
FROM node:22.19.0-slim AS production
WORKDIR /app
# npm run startを実行するためにpackage.jsonをコピーする
COPY --chown=node:node --from=production-dependencies-env /app/package.json /app/package-lock.json /app
# アプリケーションの実行に必要なパッケージをコピーする
COPY --chown=node:node --from=production-dependencies-env /app/node_modules /app/node_modules
# Next.jsアプリケーションのビルド結果をコピーする
COPY --chown=node:node --from=development-dependencies-env /app/.next /app/.next
# リソースをコピーする
COPY --chown=node:node --from=development-dependencies-env /app/public /app/public
# ポートを公開する
EXPOSE 3000
# 実行する
WORKDIR /app
USER node
CMD ["npm", "run", "start"]
.dockerignore
.env
.git/
.gitignore
.next/
Dockerfile
README.md
node_modules/
以下のコマンドを実行して Docker イメージを作成する。
$ docker build -t nextjs-example:0.1.0 .
以下のコマンドを実行して、一覧にnextjs-exampleが存在すれば Docker イメージの作成に成功している。
$ docker images
REPOSITORY                      TAG           IMAGE ID       CREATED          SIZE
nextjs-example                  0.1.0         281ecaea52cb   51 seconds ago   700MB
Docker イメージを Distribution にプッシュする
以降 Distribution をデプロイしているホストの IP アドレスと Distribution のポート番号をxxx.xxx.xxx.xxx:xxxxと表現する。
タグを作成する。
$ docker tag nextjs-example:0.1.0 xxx.xxx.xxx.xxx:xxxx/nextjs-example:0.1.0
Distribution にプッシュする。
$ docker push xxx.xxx.xxx.xxx:xxxx/nextjs-example:0.1.0
docker push時にhttp: server gave HTTP response to HTTPS clientというエラーが出る場合
docker push時に以下のエラーが発生することがある。
$ docker push xxx.xxx.xxx.xxx:xxxx/nextjs-example:0.1.0
The push refers to repository [xxx.xxx.xxx.xxx:xxxx/nextjs-example]
Get "https://xxx.xxx.xxx.xxx:xxxx/v2/": http: server gave HTTP response to HTTPS client
これを解決するにはDocker イメージをプッシュする側の/etc/docker/daemon.jsonにて以下の設定を行う。ファイルがない場合は作成する。
{
  "insecure-registries": ["xxx.xxx.xxx.xxx:xxxx"]
}
以下のコマンドを実行し、Docker を再起動する。
$ sudo service docker restart
再度プッシュを試す。
Distribution に Docker イメージが登録されていることを確認する
Docker Registry UI にアクセスして、プッシュした Docker イメージが存在することを確認する。
Distribution に登録した Docker イメージを起動する
Distrubution から Docker イメージをプルし、起動する。
ローカルに Docker イメージがある場合、以下のコマンドで消しておく。
$ docker rmi -f xxx.xxx.xxx.xxx:xxxx/nextjs-example:0.1.0
以下のコマンドを実行する。
$ docker run -p 8082:3000 xxx.xxx.xxx.xxx:xxxx/nextjs-example:0.1.0
Unable to find image 'xxx.xxx.xxx.xxx:xxxx/nextjs-example:0.1.0' locally
0.1.0: Pulling from nextjs-example
Digest: sha256:895c9b761a593f98979b806e2ca0128c6f86d7c9dd7c78b3818bf6f8e349f08f
Status: Downloaded newer image for xxx.xxx.xxx.xxx:xxxx/nextjs-example:0.1.0
> nextjs-example@0.1.0 start
> next start
   ▲ Next.js 15.5.3
   - Local:        http://localhost:3000
   - Network:      http://yyy.yyy.yyy.yyy:3000
 ✓ Starting...
 ✓ Ready in 250ms
上の例だとポート 3000 を 8082 に割り当てているので、http://localhost:8082にアクセスし、以下の画面が表示されれば Distribution に登録した Docker イメージの起動に成功したと言える。
その他
Distribution の状態は以下の API でも把握できる。
# イメージの一覧
http://xxx.xxx.xxx.xxx:xxxx/v2/_catalog
# タグの一覧
http://xxx.xxx.xxx.xxx:xxxx/v2/image-name/tags/list




