マルチプラットフォーム対応Docker imageを配布してGitHub Codespacesで動かす
やりたいこと
Docker ImageをDockerHubにpushして、GitHub Codespaceで動作させたい
ただし,
- Docker Imageは,ARM64/AMD64 両環境に対応したマルチプラットフォーム対応であること
なぜマルチプラットフォーム対応(AMD64/ARM64)したいか
AMD64
2024年1月現在,GitHub Codespaces がこの環境のみサポートしているから
GitHub Community Disscussion によると
Currently Codespaces only offers Linux as the OS and x86_64 as the architecture for the host machines. Other OSes and architectures are under consideration, and would likely come from Azure's pool of VM types: azure.microsoft.com/en-us/pricing/details/virtual-machines/series
ARM64
本プロジェクトの開発者のうち,M1 MacなどARM64環境でDevContainerを立ち上げたい人が一定数いるから(私含め)
経緯
- CyTeXというGitHub Codespace上で動作するLaTeX環境をメンテしている。
- 今までは既存のDocker Imageをpullしてビルドしていたが、自プロジェクト用のImageを用意したくなった。
- 理由としては、Dockerfile を変更する必要が生じて、どうせならビルド済みImageを配布した方が良いだろうとなったため
- というのは、無料枠での GitHub Codespaces では利用上限があるため、できるだけCPU稼働時間が少ない方が良いから
最終到達目標
- 私のM1 Mac(ARM64) で DevContainer を立ち上げられること
- GitHub Codespaces (AMD64) で環境を立ち上げられること
結論
-
DockerHub リポジトリを作成
-
Dockerfile を用意
-
docker buildx
コマンドでマルチプラットフォーム対応イメージをビルド & pushdocker buildx build --no-cache \ --push \ --platform linux/amd64,linux/arm64/v8 \ -t イメージ:タグ .
-
docker-compose.yaml を作成
docker-compose.yaml
docker-compose.yamlversion: "3.8" services: サービス名: image: イメージ名 # Dockerfileを使ってビルドしたい場合,コメントアウトする # build: . # Dockerfileを使ってビルドしたい場合,コメントアウトを外す command: sleep infinity volumes: - ../:/workdir - ~/.gitconfig:/root/.gitconfig environment: SHELL: "/bin/bash"
-
devcontainer.json
を作成devcontainer.json
devcontainer.json{ "name": "DevContainer名", "dockerComposeFile": "docker-compose.yaml", "service": "サービス名", # docker-composeで動作させたいサービス "workspaceFolder": "/workdir", "shutdownAction": "stopCompose", "customizations": {} }
-
DevContainer と Codespaces でビルドして動作確認
現状できていること
既存のDocker Imageを利用したDevContainer/Codespaces環境は,すでに構築できている.
これから独自のDocker Imageを作成して入れ替えたい.
- devcontainer.json
- docker-compose.yaml
- Dockerfileはない,これから作る
作業方針
作業の全体像が見えていないので手探りであるが、現時点のイメージ
- Dockerfile をいじいじ
- ローカルDockerでビルド
- DevContainerを起動して動作確認
- マルチプラットフォーム対応Imageへのビルド
- DockerHubへpush
- GitHub Codespaces で起動して動作確認
特に,マルチプラットフォーム対応Imageへのビルドは全く初挑戦なのでかなり試行錯誤になりそう
Dockerfile の変更,DevContainerの起動
Dockerfile を追加してDevContainerを起動すると,問題なく動作した.
Dockerfile
Dockerfileを追加
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
xdvik-ja \
evince \
texlive-full \
latexmk \
language-pack-ja \
wget \
xzdec \
git \
cpanminus \
make \
perl \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN tlmgr init-usertree
RUN kanji-config-updmap-sys ipaex
WORKDIR /workdir
VOLUME ["/workdir"]
CMD ["bash"]
docker-compose.yml
ローカルのDockerfileを使用してコンテナをビルドするよう変更
version: "3.8"
services:
cytex-texlive:
- image: 既存のdocker image
+ build: .
command: sleep infinity
volumes:
- ../:/workdir
- ./.latexmkrc:/root/.latexmkrc
- ~/.gitconfig:/root/.gitconfig
environment:
SHELL: "/bin/bash"
devcontainer.json
特に変更なし
{
"name": "cytex",
"dockerComposeFile": "docker-compose.yml",
"service": "cytex-texlive",
"workspaceFolder": "/workdir",
"shutdownAction": "stopCompose",
"customizations": {
"vscode": {
"settings": {
"extensions.verifySignature": false
},
"extensions": [
"james-yu.latex-workshop",
"MS-CEINTL.vscode-language-pack-ja",
"mhutchie.git-graph",
"eamodio.gitlens"
]
}
}
}
マルチプラットフォーム対応イメージへのビルド手法の検討
まずは選択肢を調査
Multi-platform images | Docker Docs を見てみると,以下の3戦略がありそう
You can build multi-platform images using three different strategies, depending on your use case:
- Using the QEMU emulation support in the kernel
- Building on a single builder backed by multiple nodes of different architectures
- Using a stage in your Dockerfile to cross-compile to different architectures
各選択肢を検討
1. QEMU
QEMU が何かをあまりよくわかっていないが,↓で似たことをやろうとしていて失敗していた.
arm64のM2 MacでDockerを使ってx86-64の実行環境を作る
理由が記載されていないので詳しくはわからないが,一旦他の選択肢を見てみる.
docker-buildxとmulti-platform build周りについてまとめ で↓と紹介されていた.
buildxを使って例えばamd64環境でarm向けのイメージを作成する場合は、buildx本体以外にもQEMUというエミュレータをインストールしておく必要があるらしい。
QEMUについて詳しく知りたい人は下記を読むと良さそうだけど、多分buildxについては下記の記事にある user mode emulation を使ってarmなどのCPUアーキテクチャをエミュレーションを行うために利用しているっぽい。
armなどのCPUアーキテクチャをエミュレーションを行いたいわけでないので一旦スルーする.
2. multiple nodes of different architectures
詳しくは咀嚼しきれなかったが,docker buildx
コマンドを使ってmulti-platform buildできるっぽい.
buildx について入門記事を調べてみると,↓の良さげな記事を発見.
docker-buildxとmulti-platform build周りについてまとめ
一旦docker buildx
を試したい.
3. cross-compilatoin
この選択肢も一応見ておく.
Multi-platform images | Docker Docs より,
Depending on your project, if the programming language you use has good support for cross-compilation, multi-stage builds in Dockerfiles can be effectively used to build binaries for target platforms using the native architecture of the build node. Build arguments such as BUILDPLATFORM and TARGETPLATFORM are automatically available for use in your Dockerfile, and can be leveraged by the processes running as part of your build.
クロスコンパイル可能なプログラミング言語を使っているプロジェクトなら有用とのこと.
ただ今回は,Docker上でtexliveを動かすというプロジェクトなので違う気がする.
暫定結論
docker buildx とやらが良さそうなので,こいつを試してこう
docker buildx によるマルチプラットフォーム ビルドを試す
を参考に進めていく
環境構築
- docker buildx:環境構築の必要はない.Docker Desktop に付属されているとのこと.
- DockerHub Repositoryの作成:ran350/cytex-texlive を作成
ビルド & DockerHub へのpushしてみる
$ docker buildx build --no-cache \
--push \
--platform linux/amd64,linux/arm64/v8 \
-t ran350/cytex-texlive:0.0.1 . \
.
40分くらいかかって完了した.結構かかるな 🤔
DockerHub を見てみる
OS/ARCH をみると,ちゃんと linux/amd64
と linux/arm64
が含まれている.
DockerHub へ push した image を使ってビルドしてみる
docker-compose.yaml の変更
ローカルのDockerfileではなく,DockerHub のimageを使ってビルドするよう docker-compose.yaml
を変更する.
docker-compose.yaml
version: "3.8"
services:
cytex-texlive:
- build: .
+ image: ran350/cytex-texlive:0.0.1
command: sleep infinity
volumes:
- ../:/workdir
- ./.latexmkrc:/root/.latexmkrc
- ~/.gitconfig:/root/.gitconfig
environment:
SHELL: "/bin/bash"
DevContainer でビルド & 動作確認
問題なく動作した 🙌
Codespaces でビルド & 動作確認
問題なく動作した 🙌
結論
-
DockerHub リポジトリを作成
-
Dockerfile を用意
-
docker buildx
コマンドでマルチプラットフォーム対応イメージをビルド & pushdocker buildx build --no-cache \ --push \ --platform linux/amd64,linux/arm64/v8 \ -t イメージ:タグ .
-
docker-compose.yaml を作成
docker-compose.yaml
docker-compose.yamlversion: "3.8" services: サービス名: image: イメージ名 # Dockerfileを使ってビルドしたい場合,コメントアウトする # build: . # Dockerfileを使ってビルドしたい場合,コメントアウトを外す command: sleep infinity volumes: - ../:/workdir - ~/.gitconfig:/root/.gitconfig environment: SHELL: "/bin/bash"
-
devcontainer.json
を作成devcontainer.json
devcontainer.json{ "name": "DevContainer名", "dockerComposeFile": "docker-compose.yaml", "service": "サービス名", # docker-composeで動作させたいサービス "workspaceFolder": "/workdir", "shutdownAction": "stopCompose", "customizations": {} }
-
DevContainer と Codespaces でビルドして動作確認