Dockerとは
pythonやphpで開発するときに、使用するライブラリーの関係で現在入れているバージョンではできなことが時々あります
パソコンが複数台あれば専用機を作って試すとかできますが、もったいない。pythonなら環境をコマンドで切り替えもできますが、面倒。そこでDockerを使ってなんとかならないか試してみました
Dockerの準備
Dockerはコンテナ仮想化技術を使って、作りたい環境をコンテナの中に作って、複数のコンテナの中に複数の環境をバーチャルに作ってしまうものを簡単に扱えるようにしたソフトウェアです。
一般的にはOSの上にアプリが乗りますが、これだと環境設定は切り替えはできても同時に使える環境はいづれか1つになります。ホスト型ではOSの上にホスト型仮想化のソフトウェアを入れて、その中にゲストOSを別に入れます。環境を複数作れますがソフトウェアでシミュレートしている感じです。
そこでハイパーバイザーの中にOSを複数入れられるようにする方法ができました。この方がさくさく動きます。そしてDockerですが、黒枠の中がコンテナで、そこに環境とプログラムが入ります。WindowsのDockerの場合はWSL2またはハイパーバイザーを借りることになります。Dockerはlinuxのディストリビューションではなくcoreを使用します
似たようなもんじゃないかと思わるかもしれませんが、Dockerの良いところは、すぐ消せることです。失敗してもすぐ消して、修正して、すぐ始められる。なにせOSのインストールは初回の1回だけですみますから。
Dockerを行う手順 - Windowsの場合
Dockerのダウンロード
www.docker.comに行きます。
青いdownloadのボタンにマウスをかざすと、OSの種類を聞いてきますので、それぞれ選んでください。Windowsであれば windowsのAMD64です。
Docker Desktopのインストール
ダウンロードフォルダーに「Docker Desktop Installer.exe」があります。以前のインストールでは先にWSL2を有効にする作業が必要でしたが、現在のバージョンではインストールの工程で自動的にその作業もしてくれるので、そのままインストールしてください。
Installer.exeをダブルクリックします。アカウント制御の画面が出たら「はい」をクリックします。同様のものがもう一回出るかもしれませんがそれも「はい」です。
そしてDockerの特徴であるLinuxのCoreをどこから使うかの質問が出ます。
「Use WSL2 instead of Hyper-V(recommended)」(Hyper-VよりもWSL2の方をお勧めします)
「Add shortcut to desktop」(デスクトップにショートカットを作りましょうか?)
の両方にチェックを入れて「OK」を押してください
「Installation succeeded」と表示されたらインストール修了です。「Close And Restart」を押して再起動してください
再起動とセットアップ
パソコンを再起動すると「Docker Subscription Service Agreement」の画面が表示されます。実はDockerは個人使用や中小企業は無料ですが、それ以外は有料です。我々は教育用ですので無料で行います。「Accept」をクリックして承諾してください。
次の画面でWSL2の自動更新のままでよいので「Finish」をクリックします
最初の起動とアンケート
そして最初のDocker Desktopの起動になりますが、Sign Upを求められますが必須ではありません。「Continue without signing in」をクリックしてください。
アンケートで、お仕事は何ですか?と聞かれます
最後に「Tell us about the work you do」(どんなことにお使いですか?)と聞いてきます。私は「Learning or teaching」にしました。で「Continue」をクリックします
空のコンテナが表示されます
ようやく空っぽのコンテナが表示されたと思います
これで準備OKです
Dockerで色々な環境を作る
Dockerに入れるようなものは大体決まっていますので、そういうものをDockerがDocker HubというWeb上のサイトに載せてくれています。それをimageといいます。
われわれの作業はそのimageを選んで「Pull」(download)してDockerを使って「Continer」(コンテナ)に環境を作り「Run」(実行)するのです
コンテナはそれぞれ独立していますので、ほかの設定が邪魔することはありません。しかし、その分だけ領域は使用します。
また今表示されているDocker Desktopは操作パネルであって、細かい設定をしたりするものではありません。どのimageを使うのか、同様な設定にするかは設定ファイルをいくつか作って、それをコマンドプロンプトでコマンドを手入力して操作します。
デスクトップの左側に上から「コンテナ」「イメージ」「ボリューム」「ビルド」のアイコンが並んでいます。Docker HubからPullしたものがイメージに保存されます。いらなくなれば消せます。そのイメージをRunすると「コンテナ」に表示されます。これも使い終わったら消せます。設定ファイルは適当なフォルダーの中にそれぞれ作ります。そしてそのフォルダー内でコマンドプロンプトを実行するのです。
たとえばHTMLファイルや作成したデータベースなど、取っておいて使いたいものがあると思いますが、何もしないとそれらのデータは消去で消えてしまいます。そこで「ボリューム」を設定ファイルで宣言すると、Dockerのバーチャル空間のファイルがそれぞれのフォルダーの中に同期して残り、再利用ができるようになります。apacheなどでpublic_htmlフォルダーにftpで送るのと同じように指定したフォルダー内に/srcなどのフォルダーにindex.htmlなどを入れておけば、同期してくれるのです。
設定ファイルでイメージを作るには、言語コンパイラと同じようにビルドを行います。その履歴が「ビルド」に入ります。ビルドが失敗すると実行できませんので履歴のエラーログをみて修正してください。
apache環境を作ってみる
ではまず単純にapacheつまりhttpdのイメージをPullして、index.htmlを表示するだけのコンテナを作ってみましょう。
たとえばドキュメントフォルダーにdockerフォルダーがあるとして、apache実験用のフォルダーと設定ファイルを作ります
> mkdir apachetest > cd apachetest
そのフォルダーにcompose.yamlを作ります
services: web: image: httpd:2.4 ports: - "8000:80" volumes: - ./src:/usr/local/apache2/htdocs
このyamlファイル、インデントが重要です。左端から始まり、次のインデントはスペース2つです。なのでweb:は2つスペースを入力してから書き始めます。次の行のimageは4つスペース。:の後ろは1つスペースを入れてhttpdです。間違えると動きません。
よくサンプルサイトで全部インデント0に表示されているのがありますが、意図と違います
webはサービス名、httpdがDocker Hub上のimage名で:2.4がバージョンです。portsがポートでapacheの80ポートを8000ポートにフォワードすることになります。 volumesは以下に作ったsrcフォルダーを同期しますよという意味です。この/usr/localはあくまでもバーチャルで作成したシステムの中でのフォルダーなので、ubuntuに切り替えてみてもそこにはありません。コンテナが動いているとき/srcの中身を書き換えると同期されます。ftpのようにコピーする必要はありません。
compose.yamlのサンプルをネット上で検索するとdocker-compose.ymlが表示されることが多いですが、それはバージョンが古いです。しかし先頭のversion:以外は大体使えるのでそれでもかまいません。
srcフォルダーを配下に作りindex.htmlを入れます。なんでもいいです
<html><body><h1>Congratulations. apache working</h1></body></html>
そしてDockerのコマンドを入力します
> docker compose up -d
composeがcompose.yamlを使って環境を整えてくれるツールで、upすることでビルドして実行までしてくれます。-dがついていると、実行してすぐにコマンドプロンプトに戻て来てくれます。つけないと実行中は次のコマンドが入力できなくなります。
これでDocker Desktopのコンテナをみると、runしているのがわかります
ここでこのコマンドをいれてエラーになった場合、
> docker compose up -d error during connect: Get "http://%2F%2F.%2Fpipe%2FdockerDesktopLinuxEngine/v1.46/containers/json?all=1&filters=%7B%22 label%22%3A%7B%22com.docker.compose.config-hash%22%3Atrue%2C%22com.docker.compose.project%3Dapachetest%22%3Atrue%7D%7D": open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.
これはDocker Desktopを起動していない時で、Docker engineが動いていないのです。Docker desktopを起動してからやってください。
失敗しているとrunningにならずExitedなどになっています。compose.yamlはちょっとでも間違えると動かないので気を付けましょう
さて、apacheは起動されたでしょうか。ブラウザを立ち上げて「localhost:8000」に接続します
動きましたか?
では、この現在動いているコンテナの中に入ってみましょう。コンテナはバーチャルですが、runningの今は接続できます。
> docker compose exec web /bin/bash
composeのexecコマンドでcompose.yamlで指定したサービス名を記述、コマンドラインを呼び出します
コンテナに接続して、apacheのhtdocsの中身が同期されておるのがわかったでしょうか
接続を終了するときは
# exit
「exit」と入力してコマンドプロンプトに戻ります
続いて、コンテナの終了です
> docker compose down
これでコンテナは終了します。使い終わったら消すのがお作法です
コンテナは消しましたが、imageは残っています。なのでまた upすればすぐにコンテナを再生できます。
imageも消したい場合は
> docker images -a > docker rmi {IMAGE ID}
コンテナを削除するときにimageも一緒に消したい場合は
> docker compose down --rmi all
xampp環境を作ってみる
いままでphpやデータベースを学習するのに「xampp」を使っていました。しかしphp7を勉強しようとしたら最新のxamppはphp8になっていたり、少し設定がおかしくて動きがおかしいなんてことはざらにあります。
そこでxamppの代わりにdockerが使えないか試してみました。まずはphp8バージョンです
もう細かいことは抜きでファイルの説明だけします。自分でやってみてください
postxampp compose.yaml Dockerfile +--src dbsample.php phpinfo.php
ここにDockerfileというものが登場しました。Dockerfileはcompose.yamlで作ったコンテナの中での追加設定やバージョンの指定をあらかじめ書いておく設定ファイルです
services: db: image: mariadb:10.7 environment: MARIADB_ROOT_PASSWORD: rootpass MARIADB_DATABASE: testdb MARIADB_USER: testuser MARIADB_PASSWORD: testpass volumes: - db-data:/var/lib/mysql phpmyadmin: image: phpmyadmin:5.2 depends_on: - db environment: PMA_HOST: db PMA_USER: testuser PMA_PASSWORD: testpass ports: - "8080:80" volumes: - phpmyadmin-data:/sessions apache: build: . depends_on: - db container_name: 'apache' ports: - "8000:80" volumes: - ./src:/var/www/html volumes: db-data: phpmyadmin-data:
サービスが3つ。dbとphpmyadminとapacheです。インデントはすべてスペース2つでやっています。間違うと動きません。
phpmyadminのportを8080にして、apacheを8000にして、htdocsを/var/www/htmlにしています。
FROM php:8.0-apache RUN apt-get update && apt-get install -y libonig-dev && docker-php-ext-install pdo_mysql
php8を使用し必要なライブラリーを取り込んでいます。他に必要なものがあれば追加しておけばすぐに使用できます。ここに書いてなくてもコンテナにexecで接続して追加はできます
<?php try { $dsn = 'mysql:host=db;dbname=testdb;charset=utf8'; $db = new PDO($dsn, 'testuser', 'testpass'); echo "接続に成功しました"; } catch (PDOException $e) { echo "接続に失敗しました"; echo $e->getMessage(); exit(); } ?>
またphpのバージョンをチェックするために、phpinfoを実行します
<?php phpinfo(); ?>
では「docker compose up -d」でコンテナを実行して、つないでみましょう。「localhost:8000/dbsample.php」です
またphpバージョンのチェックです。「localhost:8000/phpinfo.php」で見てみましょう
phpmyadminもチェックしましょう。portを8080にしておいたので「localhost:8080」です
できましたか?では今度はphp7をやってみましょう。一度コンテナもイメージも消しておきましょう
php7にするには、Dockerfileを書き換えるだけです
FROM php:7.4-apache RUN apt-get update && apt-get install -y libonig-dev && docker-php-ext-install pdo_mysql
php7で動いていますね
pythonの2と3を作ってみる
phpの切り替えができましたのでpythonでやってみましょう
pytest compose.yaml Dockerfile +--opt sample.py
compose.yamlやDockerfileは同じように作り/optフォルダーにサンプルプログラムを入れます
services: python3: restart: always build: . container_name: 'python3' working_dir: '/root/' tty: true volumes: - ./opt:/root/opt
FROM python:3 USER root RUN apt-get update RUN apt-get -y install locales && \ localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 ENV LANG ja_JP.UTF-8 ENV LANGUAGE ja_JP:ja ENV LC_ALL ja_JP.UTF-8 ENV TZ JST-9 ENV TERM xterm RUN apt-get install -y vim less RUN pip install --upgrade pip RUN pip install --upgrade setuptools
python3を指定して、環境編巣も設定しておきます
「docker compose up -d」でコンテナを作りましょう。
またコンテナに接続してpython3を実行してみましょう
ではpython2に切り替えましょう
phpの時と同じように設定ファイルをさわります
compose.yamlやDockerfileは同じように作り/optフォルダーにサンプルプログラムを入れます
services: python2: restart: always build: . container_name: 'python2' working_dir: '/root/' tty: true volumes: - ./opt:/root/opt
FROM python:2 USER root RUN apt-get update RUN apt-get -y install locales && \ localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 ENV LANG ja_JP.UTF-8 ENV LANGUAGE ja_JP:ja ENV LC_ALL ja_JP.UTF-8 ENV TZ JST-9 ENV TERM xterm RUN apt-get install -y vim less RUN pip install --upgrade pip RUN pip install --upgrade setuptools
python2を実行します
これで両方の環境で実行ができますね