はじめまして、Legalscapeエンジニアリングマネージャーの小林です。
今回は、DockerfileのCOPYが便利になっているのを発見したので紹介していきたいと思います。
DockerfileのCOPYは一癖ある
例えば、以下のようなディレクトリ構成において
tree
.
|-- Dockerfile
|-- package.json
`-- src
|-- a.ts
`-- b.ts
2 directories, 3 files
Dockerfileの中身が
FROM node:slim WORKDIR /app COPY package.json src ./
となっている時、このDockerfileから生成されるイメージでlsコマンドを実行すると
> docker run --rm sha256:4cd414a ls a.ts b.ts package.json
src ディレクトリが生成されていない。
cp -r では当然 src ディレクトリ配下にファイルがコピーされる。
> cd app > cp -r ../package.json ../src ./ > ls -R .: package.json src ./src: a.ts b.ts
COPY --parents
Dockerfileを以下のようにすると、COPYが cp --parents 相当の処理をするようになり、上記の問題が解決する。
#syntax=docker/dockerfile:1.7-labs FROM node:slim WORKDIR /app COPY --parents package.json src ./
> docker run --rm sha256:fd2eafe ls -R .: package.json src ./src: a.ts b.ts
pnpm workspaceを使っていると、
COPY --parents packages/**/package.json ./
のように各パッケージのpackage.jsonだけをコピーすることができ、とても便利。
#syntax=docker/dockerfile:1.7-labsってなに?
buildkitが使用するDockerfileをのparserを指定している。
buildkitは内部でllbという中間言語を経てbuildを実行しており、Dockerfileからllbへの変換に docker/dockerfile:1.7-labs を使用してくださいという指示になっている。
このように中間言語を経るおかげで、
- docker自体のアップグレードなしに新しいsyntaxを追加できる
- オレオレDockerfileを実装できる
- 例えば、 Gockerfile はGoアプリケーションを動かすDockerイメージをわずか3行のyamlでbuildできる
- 他にも、 https://docs.docker.com/build/buildkit/frontend/ を参照
というメリットがある。