こちらの記事はAnsible lint Advent Calendar 2022 7日目の記事になります。
今回はAnsible lintを実行するDockerイメージのビルド方法について解説します。コードのサンプルはこちらになります。
なぜDockerイメージを作成するのか
-
pyenvやVirtualenvでセットアップした環境が比較的壊れやすい(異論はあるかと思います)
-
Red Hatが提供しているAnsible lintがインストールされたDockerイメージ
quay.io/ansible/creator-ee
にAnsible Community Packageが入ってない -
Asibleコンテンツの開発者が増えると同一バージョンのライブラリを開発者間のローカル環境で利用するのが難しくなる
もしcreator-ee
のイメージを利用する事に問題なければメンテナンスコストを考えるとそちらを利用した方がよいかと思います。
しかし現時点ではAnsible Community Packageがcreator-ee
のイメージにはインストールされていません。そのためAnsible lintの全ての機能を利用できないため現実的ではないかと思います。
ファイル
以下のファイルを利用します。
- Dockerfile
- requirements.txt
FROM python:3.11.0-slim-buster as builder
# Install required packages
RUN apt-get update \
&& mkdir -p /usr/share/man/man1 \
&& pip3 install --upgrade pip \
&& apt-get install -y \
apt ca-certificates curl git locales openssh-client sudo unzip
# Copy requirements.txt
COPY requirements.txt /tmp/
# Install Ansible lint and Ansible
RUN pip3 install --no-cache-dir --no-compile -r /tmp/requirements.txt
FROM python:3.11.0-slim-buster as production
# Install required packages
RUN apt-get update \
&& mkdir -p /usr/share/man/man1 \
&& pip3 install --upgrade pip \
&& apt-get install -y git
COPY --from=builder /usr/local/lib/python3.11/site-packages/ /usr/local/lib/python3.10/site-packages/
COPY --from=builder /usr/local/bin/ansible-lint /usr/local/bin/ansible-lint
COPY --from=builder /usr/local/bin/ansible /usr/local/bin/ansible
COPY --from=builder /usr/local/bin/ansible-config /usr/local/bin/ansible-config
COPY --from=builder /usr/local/bin/ansible-connection /usr/local/bin/ansible-connection
COPY --from=builder /usr/local/bin/ansible-galaxy /usr/local/bin/ansible-galaxy
COPY --from=builder /usr/local/bin/ansible-playbook /usr/local/bin/ansible-playbook
# Remove caches
RUN find /usr/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \
&& find /usr/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf
WORKDIR /data
ENTRYPOINT ["ansible-lint"]
ENV ANSIBLE_FORCE_COLOR='1' PY_COLORS='1'
CMD ["--version"]
ansible-lint==6.9.1
ansible==7.0.0
イメージをビルドする
Dockerfile
とrequirements.txt
を同一ディレクトリへ配置し以下のコマンドでビルドします。
docker build -t <image-name>:<tag> .
使い方
Ansible lintを実行したいディレクトリで以下のコマンドを実行します。
$ docker run --rm -v $(pwd):/data <image-name>:<tag> <ファイル名>
# ディレクトリ全体
docker run --rm -v $(pwd):/data <image-name>:<tag> .
ファイル名を指定しない場合はバージョン情報が出力されます。
$ docker run --rm -v $(pwd):/data <image-name>:<tag>
ansible-lint 6.8.0 using ansible 2.13.6
簡単な解説
Ansibleは必ずインストールする
pip3 install ansible-lint
でAnsible lintをインストールするとAnsible coreしかインストールされません。これはdeprecated-moduleやfqdnなどの検査をする時に正しい結果が得られません。必ずAnsible(Ansible community packageとも言われる)をインストールします。
productionイメージはpython:slim-buster
を利用する
alpine
へPython 3をインストールして軽量化する方法もありますが手元で試してみた限りは実行速度が遅かったです。この件に関しての詳しい解説が「仕事でPythonコンテナをデプロイする人向けのDockerfile (1): オールマイティ編 | フューチャー技術ブログ」にありましたのでシェアさせていただきます。
マルチステージビルドを採用しDockerイメージを軽量化
近年の流行りです。イメージを軽量化できます。
環境変数にANSIBLE_FORCE_COLOR='1'
およびPY_COLORS='1'
を設定しログの表示に色をつける
好みです。
Ansible lint・Ansibleのバージョンはrequirements.yml
へ記述する
Dockerfileへ直接記述してもよいですがこの辺りはビルドの戦略によります。例えばDependabotが導入される場合はrequirements.yml
が必要になります。バージョニングが必要ない場合(常に最新のAnsible lintとAnsible community packageを利用する場合)はDockerfile側にインストール処理をそのまま記述すると良いかと思います。
FROM python:3.11.0-slim-buster as builder
# Install required packages
RUN apt-get update \
&& mkdir -p /usr/share/man/man1 \
&& pip3 install --upgrade pip \
&& apt-get install -y \
apt ca-certificates curl git locales openssh-client sudo unzip
# Copy requirements.txt
COPY requirements.txt /tmp/
# Install Ansible lint and Ansible
RUN pip3 install --no-cache-dir --no-compile -r ansible-lint ansible
FROM python:3.11.0-slim-buster as production
# Install required packages
RUN apt-get update \
&& mkdir -p /usr/share/man/man1 \
&& pip3 install --upgrade pip \
&& apt-get install -y git
COPY --from=builder /usr/local/lib/python3.11/site-packages/ /usr/local/lib/python3.11/site-packages/
COPY --from=builder /usr/local/bin/ansible-lint /usr/local/bin/ansible-lint
COPY --from=builder /usr/local/bin/ansible /usr/local/bin/ansible
COPY --from=builder /usr/local/bin/ansible-config /usr/local/bin/ansible-config
COPY --from=builder /usr/local/bin/ansible-connection /usr/local/bin/ansible-connection
COPY --from=builder /usr/local/bin/ansible-galaxy /usr/local/bin/ansible-galaxy
COPY --from=builder /usr/local/bin/ansible-playbook /usr/local/bin/ansible-playbook
# Remove caches
RUN find /usr/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \
&& find /usr/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf
WORKDIR /data
ENTRYPOINT ["ansible-lint"]
ENV ANSIBLE_FORCE_COLOR='1' PY_COLORS='1'
CMD ["--version"]