pythonコードをWindowsはexeファイル、Linuxはバイナリファイルにビルドしてpythonが無い環境でも実行できる様にします。ビルドにはDocker + Github Actionsを使用するので自分でWindowsや各Linux環境を用意する必要はありません。
作るもの・完成形のリポジトリ
完成したもの以下のリポジトリにおいてあるのでそのまま自分のGithubリポジトリに複製すればGithub Actionsでビルドが実行されます。
上記リポジトリは以下の様になっています。src/main.py
が実行ファイル化対象のpythonコードです。各Github Actionのworkflow(.github/workflows/centos7.yml・linux.yml・windows.yml
)のアーティファクトとしてビルドした実行ファイルをダウンロードできます。
├── README.md
├── .github
│ └── workflows
│ ├── centos7.yml
│ ├── linux.yml
│ └── windows.yml
├── centos7
│ └── Dockerfile
├── linux
│ └─── Dockerfile
├── src
│ └── main.py
└── windows
├── Dockerfile
└── dist
Linux用の実行ファイル生成
linux/Dockerfile
を使用してbuildします。Dockerfileの中身はpythonとpyinstallerの用意だけをしています。
FROM python:3.8-buster
# ホストマシンのコードをコンテナにコピー
COPY ./src /src
WORKDIR /src
# 依存関係のインストール
RUN pip install --no-cache-dir pyinstaller
あとはこのDockerfileを使ってビルドするworkflowを.github/workflows/linux.yml
で定義しています。
name: Build for Linux
on:
push:
branches:
- main
jobs:
build-and-run:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Build Docker image
run: docker build -f ./linux/Dockerfile -t pyinstaller-linux .
- name: Run Docker container
id: run-container
run: |
docker run --rm -v $(pwd)/src:/src -v $(pwd)/linux:/linux \
pyinstaller-linux pyinstaller main.py \
--onedir --onefile --clean \
--distpath /linux/dist \
--workpath /linux/build \
--specpath /linux
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: result-artifact
path: ./linux/dist/main
やっていることは
- リポジトリチェックアウト
- Dockerfileのビルド
- ビルドしたDockerイメージでpyinstaller実行しpythonコードをビルド
- 生成した実行ファイルをアーティファクトとしてアップロード
になります。
Centos7用の実行ファイル生成
上記linux用に生成した実行ファイルをCentos7の上で実行しようとすると
[1427] Error loading Python lib '/tmp/_MEIWviqWy/libpython3.8.so.1.0': dlopen: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by /tmp/_MEIWviqWy/libpython3.8.so.1.0)
となります。これはビルドに使用したDockerイメージのGLIBCのバージョンが新しく、Centos7のGLIBCのバージョンが古いために起こっています。同様に他の古いLinux環境でも同じ問題が起こることがあります。
そのため、Centos7用のDockerfileではcentos/python-38-centos7
を使用しています。その他手順はLinux用と同じです。
FROM centos/python-38-centos7
USER root
# ホストマシンのコードをコンテナにコピー
COPY ./src /src
WORKDIR /src
# 依存関係のインストール
RUN pip install --no-cache-dir pyinstaller
Github Actionsのworkflowはほぼ同じです。
name: Build for Centos7
on:
push:
branches:
- main
jobs:
build-and-run:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Build Docker image
run: docker build -f ./centos7/Dockerfile -t pyinstaller-centos7 .
- name: Run Docker container
id: run-container
run: |
docker run --rm -v $(pwd)/src:/src -v $(pwd)/centos7:/centos7 \
pyinstaller-centos7 pyinstaller main.py \
--onedir --onefile --clean \
--distpath /centos7/dist \
--workpath /centos7/build \
--specpath /centos7
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: result-artifact
path: ./centos7/dist/main
Windows用の実行ファイル生成
行うことはLinuxと基本的に同じですが、Windows用のexeファイル生成にはWindows環境が必要であり、ここではWindowsコンテナを使用しています。
FROM mcr.microsoft.com/windows/servercore:ltsc2019
# Chocolateyのインストール
RUN powershell -Command "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"
# Pythonのインストール
RUN powershell -Command "choco install -y python --version 3.8.10"
# ホストマシンのコードをコンテナにコピー
COPY ./src /app/src
WORKDIR /app/src
# 依存関係のインストール
RUN pip install --no-cache-dir pyinstaller
Github Actionsのworkflowもruns-on: windows-2019
を指定し、Windowsの上で一連の処理を行います。またdockerコマンドの扱いも若干Linuxとは異なるので注意が必要です。
name: Build for Windows
on:
push:
branches:
- main
jobs:
build-and-run:
runs-on: windows-2019
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Build Docker image
run: docker build -f ./windows/Dockerfile -t pyinstaller-windows .
- name: Run Docker container
run: docker run --rm -v ${{ github.workspace }}\windows\dist\:C:\dist\ pyinstaller-windows powershell -Command "pyinstaller main.py --onedir --onefile --clean --distpath /dist --workpath /windows/build --specpath /windows"
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: result-artifact
path: ./windows/dist/main.exe
2023/06/29追記 Windowsのimage buildでPlease reboot the system and try to install/upgrade Chocolatey again.
以下のようなエラーでWindows用のimageのbuildで失敗するようになったので対応
Run docker build -f ./windows/Dockerfile -t pyinstaller-windows .
Sending build context to Docker daemon 107kB
Step 1/6 : FROM mcr.microsoft.com/windows/servercore:ltsc2019
---> 0e4e89ebdca4
Step 2/6 : RUN powershell -Command "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"
---> Running in 876d98c09ce8
Forcing web requests to allow TLS v1.2 (Required for requests to Chocolatey.org)
Getting latest version of the Chocolatey package for download.
Not using proxy.
Getting Chocolatey from https://community.chocolatey.org/api/v2/package/chocolatey/2.0.0.
Downloading https://community.chocolatey.org/api/v2/package/chocolatey/2.0.0 to C:\Users\CONTAI~1\AppData\Local\Temp\chocolatey\chocoInstall\chocolatey.zip
Not using proxy.
Extracting C:\Users\CONTAI~1\AppData\Local\Temp\chocolatey\chocoInstall\chocolatey.zip to C:\Users\CONTAI~1\AppData\Local\Temp\chocolatey\chocoInstall
Installing Chocolatey on the local machine
The registry key for .Net 4.8 was not found or this is forced
Downloading 'https://download.visualstudio.microsoft.com/download/pr/2d6bb6b2-226a-4baa-bdec-798822606ff1/8494001c276a4b96804cde7829c04d7f/ndp48-x86-x64-allos-enu.exe' to 'C:\Users\CONTAI~1\AppData\Local\Temp\ndp48-x86-x64-allos-enu.exe' - the installer is 100+ MBs, so this could take a while on a slow connection.
Installing 'C:\Users\CONTAI~1\AppData\Local\Temp\ndp48-x86-x64-allos-enu.exe' - this may take awhile with no output.
.NET Framework 4.8 was installed, but a reboot is required.
Please reboot the system and try to install/upgrade Chocolatey again.
At C:\Users\ContainerAdministrator\AppData\Local\Temp\chocolatey\chocoInstall\t
ools\chocolateysetup.psm1:815 char:11
+ throw ".NET Framework 4.8 was installed, but a reboot is re ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (.NET Framework ...ocolatey ag
ain.:String) [], RuntimeException
+ FullyQualifiedErrorId : .NET Framework 4.8 was installed, but a reboot i
s required.
Please reboot the system and try to install/upgrade Chocolatey again.
Windows用のDockerfileを更新しENV chocolateyVersion=1.4.0
を指定するように対応。
FROM mcr.microsoft.com/windows/servercore:ltsc2019
ENV chocolateyVersion=1.4.0 # ここを追加
# Chocolateyのインストール
RUN powershell -Command "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"
# Pythonのインストール
RUN powershell -Command "choco install -y python --version 3.8.10"
# ホストマシンのコードをコンテナにコピー
COPY ./src /app/src
WORKDIR /app/src
# 依存関係のインストール
RUN pip install --no-cache-dir pyinstaller
まとめ
WindowsとLinux環境それぞれで動くpythonコードの実行ファイル化の方法を紹介しました。また、一部の古い環境向けの対応方法としてCentos7用の手順も記載しています。今回は全部手順を揃えるためにDockerを使用してbuildを行うようにしましたが、Windowsコンテナは微妙に扱いづらく、試行錯誤するハメになりました。結局Github Actionsでビルドを実行するので、コンテナを使わない方が楽かもしれません。