Dockerの始め方(Python環境の共有)

Dockerロゴ
画像:Dockerロゴ

PythonGUIアプリを作成して、それを他の人に動作確認または修正をしてもらいたいときがあります。このとき、GUIアプリを動かすのにPythonパッケージが多数必要であったり、OSによってGUIアプリの動作が違っていたりして動作確認が難しいことがありました。

Dockerを使えば、その問題を解決できるということで、Dockerを導入したのですが、最初の一歩がわからず、環境を共有してもらうのに2、3日かかってしまいました。それなので、Dockerを使って環境を共有するまでのやり方をまとめました。Dockerのインストール方法やDockerについての説明は省いています。初学者の備忘録ですが、参考にしてもらえれば幸いです。

主に参考にした資料は以下です。

環境

  • 開発PC:Windows10 64bit
    • WSL2を導入
    • Ubuntu 20.04を導入
    • Docker Desktop for windowsを導入

構築する環境

コンテナの作成

まず、コンテナの作成をします。コンテナの作成は「docker container run <オプション><イメージ名><コンテナで実行するコマンド>」でできます。 Ubuntu20.04を動作させるコンテナの作成は以下のコマンドでできます。

$ docker container run ubuntu:20.04

イメージが手元にない場合はイメージをDockerHubからダウンロードしてきます。<オプション>と<コンテナで実行するコマンド>は上のように省略可能です。 <コンテナで実行するコマンド>を省略した場合、イメージに設定されたデフォルトのコマンドが実行されます。

ただ、上のコマンドではコンテナに入ることもできませんし、すぐにコンテナが停止してしまうのでオプションをつける必要があります。 コンテナのbash操作は以下のコマンドでできます。

$ docker container run -it ubuntu:20.04 bash

「-it」というオプションをつけることでコンテナの直接操作ができるようになります。 ちなみに「-i, --interactive」と「-t, --tty」をくっつけたオプションとなっています。

コンテナの中の環境構築

コンテナのbash操作が可能になればコンテナの中のrootディレクトリにいると思います。 コンテナの中の環境構築ではDocker特有のことはあまりないです。コンテナに入った直後にroot権限をもつので sudoコマンドなしでパッケージをインストールできます。

自分の場合ですと、インストールを早くするためにapt-getの利用リポジトリを日本サーバーに変更します(wxPythonを使うためのパッケージのダウンロードが結構かかる)。それから、Python 3.8とpipをインストールします。

# apt-getの利用リポジトリを日本サーバーに変更
$ sed -i.bak -e "s%http://archive.ubuntu.com/ubuntu/%http://ftp.jaist.ac.jp/pub/Linux/ubuntu/%g" /etc/apt/sources.list

# python3.8 と pipのインストール
$ apt update
$ apt install -y python3.8 python3-pip

wxPythonに必要なライブラリをインストールする。

# wxPythonに必要なライブラリを入れる
$ apt install -y libgtk-3-dev \
libnotify-dev \
libsdl2-2.0-0 \
libsdl2-dev

必要なPythonのパッケージをインストールする。

# Pythonのパッケージを入れる
$ pip3 install numpy 
$ pip3 install scipy
$ pip3 install matplotlib
$ pip3 install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-20.04 wxPython

コンテナにソースをコピー

環境構築ができたら、ホストからコンテナにソースコードをコピーします。 コンテナへのファイルのコピーは「docker container cp <コピー元><コピー先>」でできます。 今利用しているコンソールはコンテナのbashを表示していますので、別のコンソールを起動してコマンドを入力してください。 ただ、コンテナの名前がわからないと思いますので、「docker container ls 」 で現在稼働しているコンテナを表示させて名前を調べてください。コンテナのパスは「コンテナ名:コンテナ内のパス」 という形式で指定してください。

# コンテナの名前を調べる
$ docker container ls
CONTAINER ID   IMAGE          COMMAND   CREATED       STATUS       PORTS     NAMES  
c68db22ff87d   ubuntu:20.04   "bash"    2 hours ago   Up 2 hours            pedantic_williams  
# ソースをディレクトリごとコピー
$ docker container cp  src  pedantic_williams:/

今回は例として、srcに以下のwx_example.pyだけを入れています。

import wx

class MyApp(wx.Frame):
    def __init__(self, parent, id = -1, title = None):
        wx.Frame.__init__(self, parent, id, title)

        self.SetSize((300, 300))

        #パネルの作成
        panel_G = wx.Panel(self, id, pos=(10, 10), size=(200, 280))
        panel_G.SetBackgroundColour((0, 255, 0))

        #描画
        self.Show(True)

if __name__ == "__main__":
    app = wx.App()
    MyApp(None, wx.ID_ANY, "title")
    app.MainLoop()

GUIアプリの起動

コンテナの中でコードを実行する前に、ウィンドウをホスト側にとばすためにコンテナのDISPLAY環境変数を設定する必要があります。別のコンソールで「echo $DISPLAY」をしたりしてホスト側のDISPLAY環境変数を手に入れて、コンテナのDISPLAY環境変数に代入します。実行することでウィンドウがとんできます。

$ export DISPLAY=(ホスト側のDISPLAY)
$ python3 /src/wx_example.py

とんできたウィンドウはこんな感じです。

コンテナから飛んできたウィンドウ

コンテナのイメージ化

動作確認ができたら、exitコマンドでコンテナを停止してください。 コンテナを停止したら、「docker container commit <コンテナ名><イメージ名> 」 で、コンテナのイメージ化ができます。

$ docker container commit pedantic_williams wx_ubuntu2004

ちなみにイメージ名は大文字にするとエラーが出ますので、全て小文字にしてください。 作成されたイメージは「docker image ls」で確認ができます。

作成したイメージのタグ付け

DockerHubにイメージを登録するには名前を「<ユーザー名>/<イメージ名>:<タグ名>」 という形式でないといけません。イメージ名とタグの変更は「docker image tag <元のイメージ名><新しいイメージ名> 」 でできます。

$ docker image tag wx_ubuntu2004 setoti/wx_ubuntu2004

タグ名は省略すれば「latest」というタグ名になります。元のイメージ名は削除されずに残っていますが、「docker image ls 」でimageを確認するとIMAGE IDは同じなので実体も同じとなっています。

DockerHubへのPush

さきほど作成したイメージをDockerHubに登録します。DockerHubへイメージをpushするにはDockerHubアカウントが必要なので登録しておいてください。 アカウントができたら「docker login 」でDockerHubへログインします。ログイン状態で「docker image push <イメージ名>」をすれば、リポジトリが作成されてアップロードされます。

$ docker login
$ docker image push setoti/wx_ubuntu2004

他人が自分のイメージを使う場合

イメージをアップロードすることができましたので、Dockerをインストールしていれば、他の人は簡単に環境構築ができます。 例えば、このブログで登録したimageは以下のコマンドで使うことができます(dbind-WARNINGが出るかもしれませんが、GTKライブラリによるものなので気にしないでください)。

$ docker container run --rm -e DISPLAY=$DISPLAY setoti/wx_ubuntu2004 python3 /src/wx_example.py

「--rm」はコンテナが停止したらコンテナを即破棄するオプションです。コンテナは停止しても残り続けるため、 例のように一つのコマンドを実行するときとかに使います。また、「-e」で環境変数付きで起動することができます。

他人が書き換えたソースの動作確認する場合

他人が書き換えたソースコードの動作確認をする場合、例えば、以下のようにすればいいです。

$ docker container run --rm -e DISPLAY=$DISPLAY --mount type=bind,source=<srcまでの絶対パス>,target=/src setoti/wx_ubuntu2004 python3 /src/wx_example.py

「--mount type=bind,source=<ホストのディレクトリ>,target=<コンテナのディレクトリ> 」をつけることで、 ホストのディレクトリをコンテナのディレクトリにマウントします。<ホストのディレクトリ>のパスは絶対パスでないと駄目です。 指定ディレクトリに書き換えたwx_example.pyを置けば、コンテナの環境で動作確認ができます。

コンテナやイメージの削除

最後に後始末として停止しているコンテナを削除します。停止しているコンテナの確認は 「docker container ls -a」でできます。「-a」のオプションを付けることで停止しているコンテナも表示されます。 確認できたら、「docker container rm <削除するコンテナ名>」で削除できます。また、「docker image rm <削除するイメージ名>」でイメージの削除ができます。

$ docker container ls -a
(停止中のコンテナも含めて表示される)
$ docker container rm pedantic_williams
$ docker image ls
(イメージ名が表示される)
$ docker image rm wx_ubuntu2004 

例では、変更前のイメージ名を消しています。名前変更後のイメージsetoti/wx_ubuntu2004があるので実体は消されません。

おわりに

ここに書いた方法によるイメージの作成はあまり推奨される方法ではないみたいです。アプリ開発や運用では DockefileやDocker Composeを使うことが推奨されるようです。ただ、私的に使うにはこれでいいかなと思います。

参考文献

[1] 伊藤祐一、「たった1日で基本が身に付く! Docker/Kubernetes超入門」、技術評論社、2020年

プライバシーポリシー

個人情報の利用目的

当ブログでは、メールでのお問い合わせやコメントの際に、お名前・メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は、お問い合わせに対する回答や必要な情報をご連絡するために利用し、それ以外の目的では利用いたしません。

個人情報の第三者への開示

個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

  • 本人のご了解がある場合
  • 法令等への協力のため、開示が必要となる場合

個人情報の開示・訂正・追加・削除・利用停止

個人情報の開示・訂正・追加・削除・利用停止をご希望の場合には、ご本人であることを確認したうえで、速やかに対応致します。

Cookieについて

当ブログでは、一部のコンテンツにおいてCookieを利用しています。
Cookieとは、webコンテンツへのアクセスに関する情報であり、お名前・メールアドレス・住所・電話番号は含まれません。

また、お使いのブラウザ設定からCookieを無効にすることが可能です。
Cookie(クッキー)を無効にする設定の詳細はポリシーと規約にてご確認ください。

広告の配信について

当サイトは第三者配信の広告サービスは利用していません。
当サイトは非営利で運営しています。

当ブログでは Amazon の商品紹介を多くしていますが、アフィリエイトなどは行っていません。

アクセス解析ツールについて

当ブログでは、Googleが提供するアクセス解析ツール「Googleアナリティクス」を利用しています。 Googleアナリティクスは、トラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。この機能はCookieを無効にすることで収集を拒否することが出来ます。

Googleアナリティクスの詳細は「Googleアナリティクス利用規約」をご覧ください。

当ブログへのコメントについて

当ブログでは、スパム・荒らしへの対応として、コメントの際に使用されたIPアドレスを記録しています。 これはブログの標準機能としてサポートされている機能で、スパム・荒らしへの対応以外にこのIPアドレスを使用することはありません。

また、以下の内容を含むコメントは運営者の裁量によって削除することがあります。

  • 特定の自然人または法人を誹謗し、中傷するもの
  • 極度にわいせつな内容を含むもの
  • 禁制品の取引に関するものや、他者を害する行為の依頼など、法律によって禁止されている物品、行為の依頼や斡旋などに関するもの
  • その他、公序良俗に反し、または管理人によって承認すべきでないと認められるもの

著作権について

当ブログのコンテンツ(記事・画像・音声データ・その他プログラム)について、許可なく転載することを禁じます。引用の際は、当ブログへのリンクを掲載するとともに、転載であることを明記してください。

また、当ブログは著作権や肖像権の侵害を目的としたものではありません。著作権や肖像権に関して問題がございましたら、お問い合わせフォームよりご連絡ください。迅速に対応いたします。

リンクについて

当ブログは基本的にリンクフリーです。リンクを行う場合の許可や連絡は不要です。
当ブログの記事を参考にした場合は、リンクを掲載していただければ幸いです。
ただし、インラインフレームの使用や画像の直リンクはご遠慮ください。

免責事項

当ブログからリンクやバナーなどによって他のサイトに移動した場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当ブログのコンテンツについて、可能な限り正確な情報を掲載するよう努めていますが、誤情報が入り込んだり、情報が古くなっている場合があります。当ブログに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

プライバシーポリシーの変更について

当ブログは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。

初出掲載:2021年6月1日
最終更新:2021年6月1日

お問い合わせフォーム プライバシーポリシー

© 2021 Setoti All rights reserved.