Pythonの開発環境をコンテナ化した話
こんにちは!
最近は色々と書きたいことが溜まっていて何を書こうか悩んだのですが、今回はタイトルの通り、Python開発環境を「コンテナ化」したことについて書きたいと思います。コンピューター関係に詳しくない方だとあまりピンとこないかも知れませんが、最近のトレンドである「コンテナ化」という技術を耳にしたので、それを自分なりに使ってみたという感じですね。具体的なアプリケーションとしてはコンテナ化アプリのデファクトスタンダード「Docker」を用います。
コンテナ化とは
コンテナ化についての説明は世の中に腐るほどあるので、ここではそこまで詳しくは解説しません(というより、僕自身がそこまで深いところまで理解できていないのが現実ですがw)。さくらインターネットにDockerについての詳細な解説があり、なかなかわかりやすいので、詳細気になる方はこちらも合わせてご覧下さい。
コンテナ化が何なのかをざっくり言うと、要するに軽量な仮想マシンの「ようなもの」です。仮想マシンと言うと、以前の記事で紹介したVirtual Boxのようなアプリケーションが有名ですが、そういった従来の仮想マシンとの最大の違いは仮想OSとホストOSでカーネルを共有するところにあります。
どういうことかと言うと、Virtual boxなどの仮想マシンにおいては、アプリケーション上で仮想OS全体を再現するのでマシンパワーや記憶領域等のリソースが大量に必要になるわけですが、Dockerにおいては仮想OSに使うカーネルの部分をホストOSと共有することでリソースの消費を抑えることが出来るわけです。上記のリンクにある図がわかりやすいですね。
https://knowledge.sakura.ad.jp/13265/より引用
このような形でミドルウェア・アプリケーションをコンテナ化することで、環境をホストOSと切り離すという仮想マシンのメリットを享受しつつ、しかも軽量に動かすことができるのがポイントです。この二つを両立したことで、比較的容易・軽量に環境を別のマシンに移植できるということから、物流に使われる「コンテナ」になぞらえて「コンテナ化」と呼ばれているようですね。
ちなみに、Dockerで使われているのはLinuxのカーネルですが、Linuxへの導入はもちろん、「Docker desktop for Windows / Mac」というパッケージをつかってWindowsやMac OS上にも導入可能です。僕の場合、家のPCはLinuxのみなのであまり関係はないですが、各種OSで気軽に環境を移植できるというのは魅力なのでしょうね。
venv仮想環境の問題点
ということで、今回はこの「コンテナ」技術を使ってPythonの開発・実行環境の仮想化を行います。
もともと僕のパソコンのPythonの環境はvenvというパッケージによって仮想環境は作っているのですが、使っているうちにちょっと問題を感じていました。というのは、仮想環境といえど、使っているうちに中の環境がどうなっているのかをあまり把握できなくなって来たことです。
この手の環境構築だとよくあることだと思いますが、自分のやりたいことをやろうとすると、一度で上手くいくケースはあまり多くなく、色々とごちゃごちゃと試して試行錯誤しているうちに上手くいくことが多いです。最終的に上手くいけば良いという考え方もあるのですが、途中で試したことがどうなっているかが把握できないと、それが後々どのような影響を与えるかもわからないので、別の環境に移植しようとした時などに色々と不都合が出てくる可能性があります。前の環境では動いていたものが動かなくなった、などですね。
あとは、Pythonの場合はOS自体が管理しているPythonと、venv仮想環境上のPythonの両方があるため、インストールしたパッケージがどちらに紐付いているかがちょっとわかりにくいというのもあります。仮想環境に入る前にpipでパッケージをインストールしたりは割とやってしまいがちですし、あまり仕組みを理解していない時にやっていた残滓が後々悪さしそうだなとw
そういう意味で、一度自分が使っている環境はしっかり整理しておきたいと思っていました。今のマシンをいつまで使うかもわかりませんし、もともとジャンク機なのでいつ使えなくなるかもわからないですしね。
そんななかで、Dockerを用いた開発環境のコンテナ化のことを知ったので、せっかくなので試してみようかなと思い、今回新たに開発環境を構築したわけです。
Docker環境の構築
Dockerの環境構築を一から書いていると長くなりそうなので、このあたりは適度に省略しつつサクッと説明していきます。実際はかなり試行錯誤しながらだったので、結構時間がかかった部分なんですけどねw 事前に本やネットの情報で色々と調べていたりもしたのですが、実際に自分の手で触ってみないとわからないことが多かったなと言う印象です。
Docker自体のインストールはこのあたりを参考に。やり方は色々とあるようですが、インストールスクリプトをダウンロードして実行するのが一番楽そうだったので、それを採用しました。
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
そして、コンテナを使いやすく扱うためのユーティリティであるDocker Composeもダウンロード。こちらはpipからのインストールです。
$ sudo pip install docker-compose
これらがインストールできたら、Docker立ち上げ用の作業フォルダをつくり、設定ファイルを作っていきます。今回使った設定ファイルの内容はこちら。
リポジトリに置いてあるファイルのうちポイントとなるのが「Dockerfile」と「docker-compose.yml」の二つ。「Dockerfile」がコンテナ(正確に言うとコンテナイメージ)を作るための設定で、「docker-compose.yml」はコンテナイメージのビルドやコンテナの起動の際の設定を記述している感じですね(このあたり、きちんと説明するのが難しいですね。。。)。今回はpython実行環境用のコンテナを作るだけなのであまり関係ないですが、Docker composeは複数のコンテナ間の通信を行うときなんかに特に威力を発揮するようです(データベースサーバーとWebサーバーを別コンテナで動かして通信する場合などですね)。
使っていて詰まったポイントとしては、Dockerコンテナ内でのユーザー設定の部分です。特に設定しないとコンテナ内には(コンテナ内の)rootユーザーでログインするため、コンテナ内で起動したコードで生成されるファイルがrootユーザーの持ち物になってしまい、ホストOSのユーザーからは編集できなくなってしまいます。
これを解決するのがちょっと面倒で、ネット等でもいろいろ調べてみて下記のように対応しました。
① "setUserinfo.sh"でホストOSのUser ID(UID)とGroup ID(GID)を.envに出力
② "docker-compose.yml"のbuild, argsにて.env内のデータを"Dockerfile"に渡す
③ "Dockerfile"内でコンテナ内の環境変数としてUID、GIDを設定する
④ Entrypointの"setVolumePermission.sh"でコンテナ内でUID,GIDを指定してユーザーを作成
⑤ 上記の"setVolumePermission.sh"の末尾でuserを指定を行う
これで、コンテナ内でのデフォルトユーザーのUID,GIDがホストOSのUID,GIDと一致するので、コンテナ内で生成されたファイルもホストのユーザーから問題なくアクセス出来るようになります(ユーザー名自体は一致しなくても大丈夫です)。
Dockerを使ってみて
はじめて使い始めるということで環境構築するまではちょっと大変でしたが、一度できてしまえばだいぶ快適に使うことができますね!
個人的に気に入っているのが、(ホストと共有している作業フォルダを除き)作業中のデータがコンテナを停止するたびに消失するため、作業に伴う環境の汚れを気にしなくて良いことです。色々と試したとしても、コンテナ自体を再起動すればまた元の状態に復帰できるので、あまり深く考えずに作業できるのは大きい気がします。
ごちゃごちゃやってみて、上手く言ったところだけDockerfileやdocker-compose.ymlに設定すれば、必要最低限のものだけをコンテナの中に残せるみたいな感じです。あまり気にしないでも良いのかも知れませんが、個人的にはムダなライブラリとかが環境に残っていたりすると落ち着かないので、これは非常に嬉しい。
また、GitHubのレポジトリにコンテナ設定ファイル(Dockerfileなどなど)を残しておけば、別のマシンにも同じ環境をサクッと再現できるのが便利です。パソコンを買い替えたり、マシンのOSを変えたときなども迅速に環境をコピーできるので開発が捗りそうです。今回は僕一人の個人での扱いなのであまり関係ないですが、複数人で同じ環境で開発を行う際なんかは、このような形で環境を共有するのが一般的なのでしょうね。
実はこれを書いている時点でPythonの開発環境に限らず色々と試して使っていますが、とにかく便利の一言です。わかるようになるまではなかなか大変だったものの、ある程度使い方や扱いに慣れてくると、「とりあえずコンテナ化してみる」みたいな思考になりがちですw(それはそれで良くない気はしますが。。。)。今後も、今回学んだコンテナ化技術を使ったものを記事にしていくつもりなので、興味のあるかたは楽しみにしていただけると嬉しいです!
まとめ
今回はDockerコンテナを用いてPythonの開発・実行環境を構築した話を書きました。詳細に説明するととても長くなるのでかなりガッツリ割愛しましたが、なんとなくの雰囲気を受け取っていただければ幸いです。どうせ、Dockerについて知っている方であれば、コードを読めば何をやっているかはわかるでしょうしね。
本文にも書いたとおり、今後もDockerを使って色々とやっていることを書いていくつもりなので、何かしらの参考になれば幸いです。
それでは、また!