私のブログでも同様の記事を昔に書いたことがあるのですが、
Python cryptography がインストールできなくなったら rustup で rust をインストールする | ytyng.com
Pipenv 等のバージョンロックシステムを使い、Alpine Linux の Docker イメージで Python 環境を構築しようとすると、インストールがうまくいかず躓く場合が多くあります。
Intel CPU でビルドがうまくいったとしても、同じ Dockerfile で Apple Silicon チップだとビルドに失敗する場合もあり、なかなか安定しません。
※ Intel CPU、Apple CPU 両方で docker build --platform linux/amd64
オプションをつけてビルドしても、結果が安定しない場合があります。
解決方法としていくつかありますので、メモをしておきます。
Python cryptography がインストールできなくなったら rustup で rust をインストールする | ytyng.com
この、以前書いた方法で行います。ただし、この場合、Intel CPU だと安定してビルドできますが、Apple CPU だと下記のようなエラーが出てビルドができない場合があります。
Failed to install some dependency or packages. The following have failed installation and attempted retry: [Requirement(_name='cryptography', vcs=None, req=NamedRequirement(name='cryptography', version='==37.0.4', req=Requirement.parse('cryptography==37.0.4; python_version >= "3.6"'), extras=[], editable=False,
また、Rust のインストールと cryptography のビルドで非常に時間がかかります。
Dockerfile はだいたいこのような形になります。
FROM alpine:3.15 as my-app-builder
MAINTAINER ytyng
# apk --virtual=.build-deps add → apk del .build-deps をすると、
# reqests とか six が消えてしまうので行ってはいけない。
RUN apk --no-cache add \
python3 \
py3-pip \
python3-dev \
gcc \
make \
python3-dev \
musl-dev \
libffi-dev \
mariadb-dev \
postgresql-dev \
g++ \
libgcc \
libstdc++ \
libxml2-dev \
libxslt-dev \
jpeg-dev \
git \
openssh \
curl \
&& curl https://sh.rustup.rs -sSf | sh -s -- -y \
&& pip3 install pipenv --ignore-installed distlib \
&& mkdir ~/.ssh/ && ssh-keyscan -t rsa github.com > ~/.ssh/known_hosts
COPY Pipfile /tmp/Pipfile
COPY Pipfile.lock /tmp/Pipfile.lock
RUN --mount=type=ssh source /root/.cargo/env \
&& PIPENV_PIPFILE=/tmp/Pipfile pipenv sync --system \
&& rustup self uninstall -y \
&& rm -rf /var/cache/apk/* \
&& rm -rf /tmp/*
FROM alpine:3.15
## ビルドイメージで作ったバイナリをコピー
COPY --from=my-app-builder /usr/lib/python3.9/site-packages/ \
/usr/lib/python3.9/site-packages/
RUN apk --no-cache add \
python3 \
bash \
libxml2 \
libxslt \
libressl \
&& ln -s /usr/bin/python3 /usr/bin/python
USER nobody
WORKDIR /var/src/
COPY . /var/src/
もし、上記の Rust で cryptography をインストールする方法がうまくいかない(もしくは、遅いので避けたい) 場合、pipenv で cryptography はインストールせず、apk でインストールするとうまくいきます。
(つまり、cryptography のバージョンロックは諦めます。)
Pipenv.lock を使って、pipenv sync コマンドで環境を作りたい場合は、事前になんらかの方法で Pipenv.lock から cryptography の項目を削除し、予め apk で py3-cryptography
をインストールするようにすれば、Rust も不要で簡潔な Dockerfile になります。
ただし、Pipenv.lock から cryptography を自動的に消す、もしくは pipenv sync で cryptography だけインストールを除外する、といった方法はわからなかったため、継続して行うには別のスクリプトが必要そうです。
FROM alpine:3.15 as my-app-builder
RUN apk --no-cache add \
python3 \
py3-pip \
python3-dev \
py3-cryptography \
gcc \
make \
python3-dev \
musl-dev \
libffi-dev \
mariadb-dev \
postgresql-dev \
g++ \
libgcc \
libstdc++ \
libxml2-dev \
libxslt-dev \
jpeg-dev \
git \
openssh \
curl \
&& pip3 install pipenv --ignore-installed distlib
COPY Pipfile /tmp/Pipfile
COPY Pipfile.lock /tmp/Pipfile.lock
RUN PIPENV_PIPFILE=/tmp/Pipfile pipenv sync --system
FROM alpine:3.15
## ビルドイメージで作ったバイナリをコピー
COPY --from=my-app-builder /usr/lib/python3.9/site-packages/ \
/usr/lib/python3.9/site-packages/
...
多少強引な方法ですが、 cryptography は apk でビルド済みのものをインストールし、そのほかの依存関係は Pipfile.lock を使わずに、Pipfile だけで pipenv install してしまう方法もありだと思います。依存関係にシビアでない、それほど重要ではない Docker イメージの場合はありだと思います。
( cryptography に限らず、Pipfile に記載されていない依存性のバージョンロックをすべて諦めます。)
Apple CPU で X86_64 向けの Docker イメージをビルドする場合はこの B か C の方法が今の所安定してビルドできています。
FROM alpine:3.15 as my-app-builder
RUN apk --no-cache add \
python3 \
py3-pip \
python3-dev \
py3-cryptography \
gcc \
make \
python3-dev \
musl-dev \
libffi-dev \
mariadb-dev \
postgresql-dev \
g++ \
libgcc \
libstdc++ \
libxml2-dev \
libxslt-dev \
jpeg-dev \
git \
openssh \
curl \
&& pip3 install pipenv --ignore-installed distlib
COPY Pipfile /tmp/Pipfile
RUN PIPENV_PIPFILE=/tmp/Pipfile pipenv install --system --skip-lock --deploy
コメント