a coffee cup and a pen on a desk

M1 MacでDockerを使ってPowerShellを動作させる

M1 MacでDockerを使用してPowerShellを動作させる際には、いくつかの課題が生じる可能性があります。

この記事では、DockerfileをM1 Macでビルドする際に遭遇する可能性がある問題とその解決策を説明します。

問題の概要

以下のDockerfileを使用してビルドを試みると、特定のエラーが発生する可能性があります。

FROM --platform=linux/x86_64 mcr.microsoft.com/powershell:7.3-ubuntu-22.04
RUN pwsh -Command Install-Module -Name Microsoft.Graph -Scope AllUsers -F

エラーメッセージは以下の通りです。

---> [Warning] The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
---> Running in 28a633eea3df
An error has occurred that was not properly handled. Additional information is shown below. The PowerShell process will exit.
An error has occurred that was not properly handled. Additional information is shown below. The PowerShell process will exit.
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault
The command '/bin/sh -c pwsh -Command Install-Module -Name Microsoft.Graph -Scope AllUsers -F' returned a non-zero code: 139

このエラーは、使用しているイメージのプラットフォームがホストと一致しない場合に発生します。

具体的には、このエラーはx86_64(AMD64)プラットフォーム向けのイメージをARM64プラットフォーム(M1 Macが使用しているプラットフォーム)で実行しようとしたときに発生します。

さらに、Segmentation faultというエラーになることもあります。

これは、プログラムが不正なメモリ領域にアクセスしようとしたときに発生します。

このエラーは通常、プログラムのバグや、プログラムが不適切な方法でメモリを操作した結果として発生します。

この場合、エラーはQEMU(異なるCPUアーキテクチャ間でのエミュレーションを提供するソフトウェア)から発生しており、x86_64プラットフォーム向けのコードをARM64プラットフォームで実行しようとしたことが原因と考えられます。

解決策

この問題を解決するためには、ARM64プラットフォーム向けのPowerShellを直接インストールする必要があります。

https://github.com/GitSumito/CodeArsenal/blob/main/Powershell_On_Docker_For_M1Mac/Dockerfile

上のリポジトリは build したDockerfile です。

以下 Dockerfile の解説です。

# Select the base image
FROM arm64v8/ubuntu:latest

この行では、ベースイメージとしてARM64プラットフォーム向けの最新のUbuntuイメージを選択しています。

# Update the package lists for upgrades for security purposes
RUN apt-get update && apt-get upgrade -y

この行では、セキュリティのためにパッケージリストを更新し、アップグレードします。

# Install necessary tools
RUN apt-get install -y curl wget tar sudo
# Install the ICU library
RUN apt-get install -y libicu-dev

この行では、ICU(International Components for Unicode)ライブラリをインストールしています。ICUは、Unicodeとグローバリゼーション(i18n)サポートを提供するC/C++およびJavaライブラリです。

# Download the PowerShell binary
RUN wget -O /tmp/powershell.tar.gz https://github.com/PowerShell/PowerShell/releases/download/v7.3.4/powershell-7.3.4-linux-arm64.tar.gz

この行では、PowerShellのバイナリをダウンロードしています。wgetコマンドを使用して、指定したURLからPowerShellのtar.gzファイルをダウンロードし、/tmpディレクトリにpowershell.tar.gzという名前で保存します。

# Create the target folder where PowerShell will be placed
RUN mkdir -p /usr/local/microsoft/powershell/7.3.4

この行では、PowerShellが配置されるターゲットフォルダを作成します。

# Expand PowerShell to the target folder
RUN tar zxf /tmp/powershell.tar.gz -C /usr/local/microsoft/powershell/7.3.4

この行では、ダウンロードしたPowerShellのtar.gzファイルをターゲットフォルダに展開します。

# Set execute permissions
RUN chmod +x /usr/local/microsoft/powershell/7.3.4/pwsh

この行では、PowerShell実行ファイルに実行権限を設定します。

# Create a symbolic link that points to pwsh
RUN ln -s /usr/local/microsoft/powershell/7.3.4/pwsh /usr/local/bin/pwsh

この行では、pwshへのシンボリックリンクを作成します。これにより、どのディレクトリからでもpwshコマンドを使用してPowerShellを起動できるようになります。

# Install necessary PowerShell modules
RUN pwsh -Command Install-Module -Name ExchangePowerShell -F
RUN pwsh -Command Install-Module -Name Microsoft.Graph -F

最後に、必要なPowerShellモジュールをインストールします。この例では、ExchangePowerShellモジュールとMicrosoft.Graphモジュールをインストールします。

Dockerfileのビルドが成功すると、以下のような出力が表示されます:

---> c6bd065a23d8
Step 6/11 : RUN mkdir -p /usr/local/microsoft/powershell/7.3.4
---> Running in 77c3cfaf924e
Removing intermediate container 77c3cfaf924e
---> 19263b7b1096
Step 7/11 : RUN tar zxf /tmp/powershell.tar.gz -C /usr/local/microsoft/powershell/7.3.4
---> Running in 6f9b149944ae
Removing intermediate container 6f9b149944ae
---> 86c0945e8a86
Step 8/11 : RUN chmod +x /usr/local/microsoft/powershell/7.3.4/pwsh
---> Running in bed70b0443d1
Removing intermediate container bed70b0443d1
---> b767beaee0b3
Step 9/11 : RUN ln -s /usr/local/microsoft/powershell/7.3.4/pwsh /usr/local/bin/pwsh
---> Running in 26c1c7b4b1cf
Removing intermediate container 26c1c7b4b1cf
---> ff72047deef1
Step 10/11 : RUN pwsh -Command Install-Module -Name ExchangePowerShell -F
---> Running in e024612672c1
Removing intermediate container e024612672c1
---> 08eb8f79bdd4
Step 11/11 : RUN pwsh -Command Install-Module -Name Microsoft.Graph -F
---> Running in 2988a85004a6
Removing intermediate container 2988a85004a6
---> 0205240f3f6f
Successfully built 0205240f3f6f
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

このDockerfileを使用することで、M1 MacでもDocker上でPowerShellを動作させることが可能になります。