はじめに
発端は友人から大学院の授業で使う環境の構築で困ったから手伝ってくれって言われた事でした。
見てみると、ubuntu上で教授が用意したバイナリファイルを実行できるようにできれば良さそうでした。
Windowsは環境構築の方法が解説されて、Macは自力で頑張ってと言われたそうです😇
Dockerを使えば実現できそうなのでやってみました。
リポジトリ
今回使用したバイナリファイルは2次配布が禁止であった為リポジトリには含めていません。各自、実行したいバイナリファイルを用意してください。
環境
macOS Catalina: 10.15.4
Docker: 19.03.8
docker-compose 1.25.5
XQuartz 2.7.11 (xorg-server 1.18.4)
X11クライアントを各自変えてあげればmacOS以外でも動作すると思います。
ゴール
下記のコマンドで簡単に実行できる様にする。
$ make up
$ make #{実行したいバイナリファイル名}
手順
0. XQuartzを導入する
macにXQuartzを未導入の場合は導入してください。
XQuartzを用いる事でMacでX11アプリケーションを動作させる事ができる様になります。
brewを導入済みの場合は下記コマンドでXQuartzを導入できると思います。
$ brew cask install xquartz
導入後は再起動かユーザーのログアウトを行わないとXQuartzの設定の反映が行われないので注意してください。
1. XQuartzのネットワーク・クライアントからの接続を許可する
XQuartzを起動できる様にできたら、XQuartzを起動し、環境設定から「ネットワーク・クライアントからの接続を許可」にチェックを入れ、XQuartzを再起動してください。
2. Dockerfileを記述する
バイナリファイルを実行する環境のDockerfileを記述しています。
実行したいバイナリファイルによって各自変更してください。
x11関連のライブラリをapt-get install
する際にタイムゾーンの設定等出てきてしまってビルドが進まなくなってしまった為、タイムゾーンを設定し、ENV DEBIAN_FRONTEND noninteractive
にて他の選択項目が出てきてしまっても進む様にしています。
今回はcommandsディレクトリにバイナリファイル(複数可)を配置する事を想定しています。
FROM ubuntu:20.04
WORKDIR usr/workdir
# TZを設定する
ENV TZ Asia/Tokyo
RUN apt-get update \
&& apt-get install -y tzdata \
&& rm -rf /var/lib/apt/lists/* \
&& echo "${TZ}" > /etc/timezone \
&& rm /etc/localtime \
&& ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
&& dpkg-reconfigure -f noninteractive tzdata
# 必要なライブラリのインストール
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update \
&& apt-get install build-essential x11-apps x11-utils x11-xserver-utils dbus-x11 -y \
&& apt-get install gedit -y \
&& apt-get install libgfortran4 -y
COPY commands/ ./commands
RUN chmod +x ./commands
ENV PATH /usr/workdir/commands:$PATH
この時点で実行できるといえばできるはずです。
参考:Docker for Mac で X11 アプリケーションを動かす
毎回長いコマンド打つのはめんどくさい、、、という気持ちの方は次の手順へ進んで下さい。
3. docker-coomposeを記述する
コンテナ側にホスト側のX11クライアントの情報を渡してあげる必要があり、コマンドを毎回打つのが面倒な為記述しました。
また、ホスト側srcディレクトリをコンテナ側/usr/workdir/srcディレクトリにマウントする様に記述しています。
version: '3.7'
services:
app:
build: .
volumes:
- ./src:/usr/workdir/src
env_file:
- .env
tty: true
stdin_open: true
docker-compose.ymlから参照している.envは下記です。
この環境変数DISPLAYをもとにコンテナ内からXQuartzへアクセスしにいきます。
DISPLAY=host.docker.internal:0
こちらの記事を参考に記述致しました。
host.docker.internalの実態としてはHost(Mac)側のhostnameを取得してくるそうです。
ここら辺の名前解決はDockerのバージョンによって推奨が違う為確認してください。
4. Makefileを記述する
毎回docker-composeコマンドを記述するのが面倒な為、Makefileを定義してあげてmakeコマンドで実行できる様にしました。
基本的にはdocker-composeをmakeで実行できるようにしています。
ポイントとしては、upで実行する際に自動的にXquartzを起動し、xhost +$(hostname)
にてホスト(Mac)のhostnameでXquartzへアクセスできる様にしてコンテナ側との整合性を合わせています。
また、xhostでのアクセスはセキュリティリスクもある為気になる方は他の方法で認証してください。
build:
docker-compose build --no-cache
up:
open -a Xquartz
xhost +$(hostname)
docker-compose up -d
down:
docker-compose down
restart:
make down
make up
destroy:
docker-compose down --rmi all --volumes
destroy-volumes:
docker-compose down --volumes
ps:
docker-compose ps
bash:
docker-compose exec app bash
xeyes:
docker-compose exec app bash -c 'xeyes'
#{実行したいバイナリファイル名}:
docker-compose exec app bash -c '#{実行したいバイナリファイル名}'
4. 実行する
下記コマンドでdockerイメージをビルドします
$ make build
buildに成功すれば下記コマンドでdockerコンテナを起動できるはずです。
$ make up
起動できたら、コンテナ側からホスト(Mac)のXQuartzへアクセスできるかxeyesを用いてテストしてみます
$ make xeyes
このような目玉が表示されればコンテナ側からホスト(Mac)のXQuartzへアクセスできています。
後は実行したいバイナリファイルを各自配置し
$ make #{実行したいバイナリファイル名}
上記コマンドを下記の様に実行してください
$ make binary
また、下記コマンドを用いてコンテナへ入ることもできます。
$ make bash
まとめ
Dockerを用いればX11を用いたLinux用バイナリファイルもMac上のプログラムを動かすかの様に簡単に動作させる事ができた!