このあいだの、MediaWiki のデータベースとして MariaDB を採用したわけだけど、バックアップのために dump するには MySQL と同じように mysqldump が使える。
こんな感じ:
$ mysqldump -P 3306 -u root -p testwiki > testwiki.sql
takatoh's blog – Learning programming languages.
このあいだの、MediaWiki のデータベースとして MariaDB を採用したわけだけど、バックアップのために dump するには MySQL と同じように mysqldump が使える。
こんな感じ:
$ mysqldump -P 3306 -u root -p testwiki > testwiki.sql
ローカルネットワークで wiki を運用してるんだけど、Docker 上に移行すべく、今日はそのテスト。
MediaWiki も MariaDB も Docker Hub に公式イメージが有るのでそれを使わせてもらう。データベースは、はじめは MySQL を試したんだけどうまく動かなかった(原因不明)ので MariaDB に変えた。
用意した構成はこんなの:
takatoh@apostrophe:testwiki$ tree . . ├── docker-compose.yml ├── mysql │ └── db └── wiki └── images
docker-compose.yml はこう:
version: '3' services: testwiki: container_name: testwiki image: mediawiki:1.35.0 restart: always ports: - 8888:80 volumes: - ./wiki/images:/var/www/html/images # - ./wiki/LocalSettings.php:/var/www/html/LocalSettings.php mysql: container_name: db image: mariadb:10.5.6-focal restart: always environment: MYSQL_ROOT_PASSWORD: rootpasswd MYSQL_DATABASE: testwiki MYSQL_USER: mysqluser MYSQL_PASSWORD: mypassword ports: - 3306:3306 volumes: - ./mysql/db:/var/lib/mysql
コメントアウトしてある行は MediaWiki の設定ファイル。これはインストールが済んでから使う。
docker-compose
コマンドでコンテナを起動する。
takatoh@apostrophe:testwiki$ docker-compose up -d
ブラウザで http://localhost:8888/ にアクセスして MediaWiki のインストール(というかセットアップというか)をする。その際、データベース関係は docker-compose.yml の記述に合わせる。
その他はそれなりに設定すればいい。最後に LocalSettings.php ファイル(設定ファイル)をダウンロードしてインストールは終わり。
いったんコンテナを止める。
takatoh@apostrophe:testwiki$ docker-compose down
ダウンロードした設定ファイルを配置。
takatoh@apostrophe:testwiki$ cp ~/Downloads/LocalSettings.php wiki
docker-compose.yml のコメントをはずす(該当行だけ示す)。
- ./wiki/LocalSettings.php:/var/www/html/LocalSettings.php
コンテナを再起動。
takatoh@apostrophe:testwiki$ docker-compose up -d
これで無事起動した。
旧い wiki からデータを移行する手順。
wiki.sql ファイルを Docker コンテナと共有しているディレクトリにコピーする。
takatoh@apostrophe:testwiki$ cp wiki.sql ./mysql/db
./mysql/db ディレクトリは、データベースの Docker コンテナ(コンテナ名は db)からは /var/lib/mysql として認識されている(前述の docker-compose.yml ファイルを参照)。なのでデータベースのコンテナに接続して、データを流し込む。
takatoh@apostrophe:testwiki$ docker exec -it db bash root@007d71dfcb37:/# cd /var/lib/mysql root@007d71dfcb37:/var/lib/mysql# ls *.sql wiki.sql root@007d71dfcb37:/var/lib/mysql# mysql -u mysqluser -p testwiki < wiki.sql Enter password: root@007d71dfcb37:/var/lib/mysql# exit exit
これでデータベース側での作業は終了。ただ、このままだと MediaWiki でエラーになる。バージョンが上がっているので MediaWiki の使用するデータベーススキーマとかも変わっているからだ。
そこで、MediaWiki のコンテナに接続して更新スクリプトを実行する。更新スクリプトは /var/www/html/maintenance/update.php だ。
takatoh@apostrophe:testwiki$ docker exec -it testwiki bash root@f92dd50471e5:/var/www/html# cd maintenance root@f92dd50471e5:/var/www/html/maintenance# php update.php
これで完了。
11/7、本番環境も無事 Docker 上に移行した。
Qiita の↓の記事を読んで、EPUB って結構簡単(もちろん単純なものなら)なんだな、と思ったので Python でスクリプトを作ってみた。
フォルダに入った画像ファイル一式から EPUB ファイルを生成する。
ファイル構成は次の通り:
takatoh@montana: img2epub > tree /f . フォルダー パスの一覧 ボリューム シリアル番号は 681C-8AA1 です C:\USERS\TAKATOH\DOCUMENTS\W\IMG2EPUB │ .gitignore │ img2epub.py │ ├─data │ book.opf.template │ chap1.xhtml.template │ container.xml │ nav.xhtml │ └─sample sample-000.png sample-001.png sample-002.png sample-003.png sample-004.png sample-005.png sample-006.png sample-007.png
img2epub.py が Python で書いたスクリプト本体。data フォルダ以下のファイルは EPUB を構成するファイルあるいはそのテンプレート。スクリプトは次の通り:
#!/usr/bin/env python # encoding: utf-8 import sys import os import shutil import subprocess from datetime import datetime, timezone import uuid import glob from jinja2 import Template, Environment, FileSystemLoader def main(): src_dir = sys.argv[1] now = datetime.now(timezone.utc) tmp_dir_name = "tmp.epub.{time}".format(time=now.strftime("%Y%m%d%H%M%S")) make_dirs(tmp_dir_name) images = copy_images(src_dir, tmp_dir_name) images = [s.replace("\\","/") for s in sorted(images)] gen_mimetype(tmp_dir_name) copy_container(tmp_dir_name) book_opf_context = { "title": src_dir, "time": now.isoformat(), "images": images } gen_book_opf(tmp_dir_name, book_opf_context) copy_nav(tmp_dir_name) gen_chap1_xhtml(tmp_dir_name, book_opf_context) zip_epub(tmp_dir_name, src_dir) def make_dirs(tmp_dir_name): os.makedirs(os.path.join(tmp_dir_name, "META-INF")) os.makedirs(os.path.join(tmp_dir_name, "EPUB")) def copy_images(src_dir, tmp_dir_name): images_dir = os.path.join(tmp_dir_name, "EPUB/images") shutil.copytree(src_dir, images_dir) return glob.glob("{dir}/*".format(dir=images_dir)) def gen_mimetype(tmp_dir_name): with open(os.path.join(tmp_dir_name, "mimetype"), "w") as f: f.write("application/epub+zip") def copy_container(tmp_dir_name): shutil.copyfile("data/container.xml", os.path.join(tmp_dir_name, "META-INF/container.xml")) def gen_book_opf(tmp_dir_name, context): env = Environment(loader=FileSystemLoader("data")) template = env.get_template("book.opf.template") context["images"] = [s.replace("{tmp}/EPUB".format(tmp=tmp_dir_name), ".") for s in context["images"]] context["cover"] = context["images"][0] context["uuid"] = str(uuid.uuid4()) with open(os.path.join(tmp_dir_name, "EPUB/book.opf"), "w") as f: f.write(template.render(context)) def copy_nav(tmp_dir_name): shutil.copyfile("data/nav.xhtml", os.path.join(tmp_dir_name, "EPUB/nav.xhtml")) def gen_chap1_xhtml(tmp_dir_name, context): env = Environment(loader=FileSystemLoader("data")) template = env.get_template("chap1.xhtml.template") images = [s.replace("{tmp}/EPUB".format(tmp=tmp_dir_name), ".") for s in context["images"]] with open(os.path.join(tmp_dir_name, "EPUB/chap1.xhtml"), "w") as f: f.write(template.render(images=images)) def zip_epub(tmp_dir_name, title): epub_file_name = "../{title}.epub".format(title=title) os.chdir(tmp_dir_name) subprocess.run(["zip", "-X0", epub_file_name, "mimetype"], stdout=subprocess.DEVNULL) subprocess.run(["zip", "-r9", epub_file_name, "*", "-x", "mimetype"], stdout=subprocess.DEVNULL) os.chdir("..") main()
で、sample フォルダ以下が元になる画像ファイル一式。
スクリプトの引数に画像一式が入っているフォルダを指定するだけ。
takatoh@montana: img2epub > python img2epub.py sample
そうすると、EPUB ファイル(今回は sample.epub)と、EPUB にまとめる前のファイル一式の入ったフォルダ(同じく tmp.epub.20201027130853)ができる。このフォルダはテンポラリなものなので消しちゃってもいいんだけど、今の段階ではまだ残している。
takatoh@montana: img2epub > ls
Directory: C:\Users\takatoh\Documents\w\img2epub
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2020/10/27 20:07 data
d---- 2020/10/27 20:09 sample
d---- 2020/10/27 22:08 tmp.epub.20201027130853
-a--- 2020/10/27 20:07 9 .gitignore
-a--- 2020/10/27 20:07 2832 img2epub.py
-a--- 2020/10/27 22:08 8011218 sample.epub
あとは出来上がった sample.epub ファイルを好きな EPUB ビューワで見ればいい。
EPUB のファイルっていうのは、基本的には使用で決められたファイルとコンテンツを zip で一つにまとめて、拡張子を .epub
にしただけのファイルだ。単純に zip にしただけではないんだけど、そのへんはこの記事では触れない。冒頭の Qiita の記事か、EPUB 3.2 の仕様を参照のこと。
今回作ったスクリプト img2epub.py では、tmp.epub.* フォルダにその一式が入っている(つまりこれを zip 圧縮して .epub
ファイルを作る)。フォルダの中身は次の通り:
takatoh@montana: img2epub > tree /f tmp.epub.20201027130853 フォルダー パスの一覧 ボリューム シリアル番号は 681C-8AA1 です C:\USERS\TAKATOH\DOCUMENTS\W\IMG2EPUB\TMP.EPUB.20201027130853 │ mimetype │ ├─EPUB │ │ book.opf │ │ chap1.xhtml │ │ nav.xhtml │ │ │ └─images │ sample-000.png │ sample-001.png │ sample-002.png │ sample-003.png │ sample-004.png │ sample-005.png │ sample-006.png │ sample-007.png │ └─META-INF container.xml
EPUB/images 以下の画像ファイルは、元のデータをコピーしたもの。そのほかのファイルはスクリプトが生成したファイルだ。詳しくは略。
EPUB を構成するファイルの一部(book.opf や chap1.xhtml)を生成するためにテンプレートエンジンを使ってるんだけど、Python には string.Template
というテンプレートエンジンが標準でついている。これ、今回調べてて初めて知った。
ところがこの string.Template
、単純な値の挿入はできるけど繰り返しや条件分岐の機能がない。今回、条件分岐は使ってないけど繰り返すは必要だったので、結局 Jinja2 を使った。標準添付されてるのはいいけど、変数を値に置き換えるだけしかできないんじゃ、用途は限られるよなぁ。
PDF をページごとの画像ファイルに変換したくて、はじめは Python でできないか調べてた。そしたら↓のページで pdf2image という(Pythonの)ライブラリを紹介しているのを見つけた。
ところが記事を読んでみるとこう書いてある:
pdf2imageは「Poppler」というフリーのPDFコマンドラインツールを背後で用います。そのため、Popplerをダウンロードしておく必要があります。
それなら Poppler をそのまま使えばいいじゃん。
というわけで、Poppler for Windows をダウンロードした。
バージョンは 0.68.0 (poppler-0.68.0_x86.7z)。7zip なので 7z コマンドをインストールしてから展開した。
展開したファイルを眺めてみると、bin フォルダの中に pdfimages.exe という実行ファイルがある。これが使えそうだ。PATH を通してとりあえずヘルプを見てみた。
takatoh@montana: tmp > pdfimages -h pdfimages version 0.68.0 Copyright 2005-2018 The Poppler Developers - http://poppler.freedesktop.org Copyright 1996-2011 Glyph & Cog, LLC Usage: pdfimages [options] <PDF-file> <image-root> -f <int> : first page to convert -l <int> : last page to convert -png : change the default output format to PNG -tiff : change the default output format to TIFF -j : write JPEG images as JPEG files -jp2 : write JPEG2000 images as JP2 files -jbig2 : write JBIG2 images as JBIG2 files -ccitt : write CCITT images as CCITT files -all : equivalent to -png -tiff -j -jp2 -jbig2 -ccitt -list : print list of images instead of saving -opw <string> : owner password (for encrypted files) -upw <string> : user password (for encrypted files) -p : include page numbers in output file names -q : don't print any messages or errors -v : print copyright and version info -h : print usage information -help : print usage information --help : print usage information -? : print usage information
出力は JPEG が欲しかったので -j
オプションを指定。<image-root>
が何を指すのかよくわからないけどテキトーに。そしたらこうなった。
takatoh@montana: tmp > pdfimages -j sample.pdf foo
takatoh@montana: tmp > ls
Directory: C:\Users\takatoh\Documents\tmp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2020/10/24 8:53 5364971 foo-000.ppm
-a--- 2020/10/24 8:53 5364971 foo-001.ppm
-a--- 2020/10/24 8:53 5364971 foo-002.ppm
-a--- 2020/10/24 8:53 5364971 foo-003.ppm
-a--- 2020/10/24 8:53 5364971 foo-004.ppm
-a--- 2020/10/24 8:53 5364971 foo-005.ppm
-a--- 2020/10/24 8:53 5364971 foo-006.ppm
-a--- 2020/10/24 8:53 5364971 foo-007.ppm
-a--- 2020/03/28 9:12 4082441 sample.pdf
.ppm
って!いまどき .ppm
ファイルなんて何で見ればいいんだ。なら PNG でいいや。あと、<image-root>
は出力ファイルのプレフィックスみたいだな。なので .ppm
ファイルは削除してやり直した。
takatoh@montana: tmp > pdfimages -png sample.pdf sample
takatoh@montana: tmp > ls
Directory: C:\Users\takatoh\Documents\tmp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2020/03/28 9:12 4082441 sample.pdf
-a--- 2020/10/24 9:01 1269290 sample-000.png
-a--- 2020/10/24 9:01 446405 sample-001.png
-a--- 2020/10/24 9:01 893712 sample-002.png
-a--- 2020/10/24 9:01 1258104 sample-003.png
-a--- 2020/10/24 9:01 1301072 sample-004.png
-a--- 2020/10/24 9:01 1344592 sample-005.png
-a--- 2020/10/24 9:01 1157016 sample-006.png
-a--- 2020/10/24 9:01 755768 sample-007.png
これで OK。だけど、欲を言えば出力されるファイルをひとつのフォルダに入れたい。それらしいオプションは見当たらないけど、プレフィックスにパスを含めてやればできた。フォルダは先に作っておくこと。
takatoh@montana: tmp > mkdir outDirectory: C:\Users\takatoh\Documents\tmp
Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 2020/10/24 11:29 out takatoh@montana: tmp > pdfimages -png sample.pdf out/sample takatoh@montana: tmp > ls outDirectory: C:\Users\takatoh\Documents\tmp\out
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2020/10/24 11:29 1269290 sample-000.png -a--- 2020/10/24 11:29 446405 sample-001.png -a--- 2020/10/24 11:29 893712 sample-002.png -a--- 2020/10/24 11:29 1258104 sample-003.png -a--- 2020/10/24 11:29 1301072 sample-004.png -a--- 2020/10/24 11:29 1344592 sample-005.png -a--- 2020/10/24 11:29 1157016 sample-006.png -a--- 2020/10/24 11:29 755768 sample-007.png
できた。
補足。
-j
オプションの説明は write JPEG images as JPEG files となっている。PDFの中身が JPEG なら JPEG で出力するってことのようだ。
出来ない、というか少なくともウチの環境では出来なかった。
Windows10 の iTunes にある音楽を新しい iMac のミュージックアプリにどうやって移行するのか、ググってみたところで見つかったのが「移行アシスタント」だ。これは同じネットワーク内にある Windows 側と iMac 側の両方で移行アシスタントを実行すると簡単にデータ(今回の目的は音楽だけだけど、これに限らない)を移行できるというもの。少なくとも Apple のページにはそう書いてある。
ところが、実際にページに書いてある手順でやろうとしたところ、そもそも Windows 版の移行アシスタントがインストールできない。ファイルをダウンロードし直したり、PC を再起動したりと色々やってみたけど、どうにもならない。移行アシスタントアプリのバージョンのせいなのかそれとも Windows の環境のせいなのか、何度やってもダメだった。
仕方がないので、Windows 側の iTunes のデータフォルダを丸ごと USB メモリにコピーして iMac に挿した。で、ミュージックアプリにインポート。時間はかかったけど、とりあえず曲の移行はできた。
が、だ。
このやり方はつまり、ミュージックアプリに新しい曲をファイルから追加しただけなので、再生回数みたいなメタデータやプレイリストは移行されてない。
これらをどうやったら Windows から持ってくれるか、調べてみたけどいい方法が見つからなかった。もしかしたらやり方があるのかもしれないけど。
で、いつまでもこれだけに構っていられないので、もう諦めることにした。プレイリストもいくつか程度しか作ってないし、作り直せばいいだろ。
というわけで、何の役にも立たない記事だな。
あ、あとこれだけは書いておく。USB メモリを Windows と Mac の両方で使うには exFAT でフォーマットしておく必要がある。
昨日、今日と2日続けて停電が発生した。午後に降った雷雨のせいだ(たぶん)。停電は短時間(1分もない)だったけど断続的に発生して、おかげで普段つけっぱなしの PC の電源が落ちた。サーバにしている PC も、だ。
雨がおさまってきたころ、PC の電源を入れて立ち上げたけど、サーバ PC で動かしている web アプリにアクセスしても繋がらなくなっていた。どうも IP アドレスが変わってしまったようだ。停電でルータの電源も落ちたからだな(たぶん)。
たいていの家庭のネットワークも同じだと思うけど、ウチのネットワークもルータの DHCP 機能を利用して各 PC に自動で IP アドレスを割り当てている。今回、ルータの電源も落ちたことで、PC を立ち上げたときに割り当てられたアドレスが変わってしまったらしい。
で、リモートではつながらないのでローカルにログインして、割り当てられている IP アドレスを確認して、hosts ファイルを修正したら繋がるようになった。
さて、もしかすると明日も雷雨で停電するかもしれないし、それでまた IP アドレスが変わってしまうようなことになればまた今日と同じ作業をしなくちゃいけなくなる。そんなのは面倒なので、DHCP で割り当てられる IP アドレスを固定にすることにした。
ルータは web インターフェイスで設定できるので、ログインしたら DHCP の設定のページで固定割り当ての設定をする。もう少し詳しく書くと、PC の NIC の MAC アドレスと、割り当てたい IP アドレスの組を登録しておくってことだ。PC が何十台もあるわけじゃないから大した作業ではない。
ともあれ、これで電源が落ちても今日みたいな作業をしなくても済むはずだ。もっと早くやっときゃよかった。
今日、久しぶりに GitHub にアクセスしたら、自分のプロファイルの下のところに「Arctic Code Vault Contributor」なる文字があるに気がついた。
何かと思って調べてみると、GitHub のリポジトリのソースコードを北極圏の島にアーカイブして1000年後まで保管するとかいう計画に選ばれたらしい。
「GitHub Arctic Code Vault」というプロジェクトに一環で、北極圏にあるノルウェーのスヴァールバル諸島の永久凍土の地下(廃坑)のなかにマイクロフィルムに保存されたソースコード(2020年2月2日に取得したスナップショット)を保存するというものだ。今回は第1回目で、頻度は明らかにされていないものの数年に一度くらいの割合でスナップショットを保存するらしい。
それにしても、オレの書いたソースコードが1000年先まで残るのか。スゲー。
……と思いながらよく読むと、アクティブなパブリックリポジトリはすべて対象になったようだ。オレの書いたコードなんて自分でしか使わないようなのばっかなんだけど、そういうことね。いや、それにしてもすごいけど。
ところで、今回保存されたソースコードの総量は約21TBとのこと。圧縮してるのかもしれないけど、以外に少ないと感じた。まぁ、ソースコードってほとんどはテキストファイルだからそんなものなのかな。
前回の記事では、Docker のネットワークを使って通信しながら、複数のコンテナを協働させた。
基本的には前回の記事のやり方でいいんだけど、サービスの数が増えたり、規模が大きくなってコンテナの数が増えたりすると、コンテナごとにコマンドを打って起動するのは面倒だ。コンテナによって指定するオプションも異なるので、それも覚えておく必要がある。
というわけで、そういう煩雑な部分を楽にしてくれるツールがある。それが Docker Compose だ。メインマシンである apostrophe をセットアップしたときに apt でインストールしておいた。
akatoh@apostrophe:docker$ docker-compose --version docker-compose version 1.25.0, build unknown
前回記事と同じ、書籍管理 web アプリと HTTP サーバ(Nginx)という構成にする。詳しくは前回記事を参照。
前回ビルドした Docker イメージが残っているので、まずはそれを使ってコンテナを起動する設定を書いてみる。
Docker Compose は docker-compose.yml という名前のファイルを読み込んで、その設定どおりにコンテナを起動してくれる。今回書いた docker-compose.yml ファイルは次の通り。
version: '3' services: bruschetta-back: image: bruschetta:1 container_name: bruschetta-back restart: always nginx-front: image: nginx-c:1 container_name: nginx-front restart: always ports: - 8080:80
service: の下に連なっているのが、Docker Compose で起動するコンテナだ。各設定項目は見ればだいたいわかるだろうからここでは説明は省略。ただ、docker
コマンドで起動するときとは次の点が違う。
特に2つ目の挙動は docker
コマンドで起動したときと違うので注意が必要だ。最初、ここでハマった。
で、これを起動するには次のようにする。
takatoh@apostrophe:docker$ docker-compose up -d
起動中のコンテナの確認。
takatoh@apostrophe:docker$ docker-compose ps
そして停止。
takatoh@apostrophe:docker$ docker-compose stop
最後にコンテナの削除。
takatoh@apostrophe:docker$ docker-compose rm
さて、今度は Docker イメージをビルドするところからやってみる。そのためには、docker-compose.yml ファイルと同じディレクトリに、イメージ作成用のファイル一式を収めたディレクトリを置いておく。こんな感じ。
akatoh@apostrophe:docker$ ls -l 合計 12 drwxrwxr-x 3 takatoh takatoh 4096 5月 9 03:15 bruschetta -rw-rw-r-- 1 takatoh takatoh 239 6月 14 13:26 docker-compose.yml drwxrwxr-x 3 takatoh takatoh 4096 5月 14 06:19 nginx-c
そして、docker-compose.yml ファイルを次のように書き変える。
version: '3' services: bruschetta-back: build: ./bruschetta image: bruschetta:1 container_name: bruschetta-back restart: always nginx-front: build: ./nginx-c image: nginx-c:1 container_name: nginx-front restart: always ports: - 8080:80
書き変えた、というか書き足したのは、build:
の行だ。この行でイメージをビルドするための Dockerfile (とその他に必要なフィアル)を置いてあるディレクトリを指定している。
ビルドするには次のようにする。
takatoh@apostrophe:docker$ docker-compose build
イメージができたか、確認。
takatoh@apostrophe:docker$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx-c 1 c8b3966bbc31 54 seconds ago 127MB bruschetta 1 7d6607e796c2 About a minute ago 468MB nginx 1.17.10 9beeba249f3e 4 weeks ago 127MB ubuntu 20.04 1d622ef86b13 7 weeks ago 73.9MB
nginx-c:1 と bruschetta:1 がビルドされたイメージ。下の2つは元になったイメージ(Docker Hub から取ってきたもの)だ。
じゃあ、これを起動してみよう。
takatoh@apostrophe:docker$ docker-compose up -d
OK。ブラウザからアクセスしてみて、期待通りに動いているのを確認できた。
Docker を使ったサービスでは、サービスを構成する各サーバプログラムをそれぞれ別のコンテナで立ち上げるのが一般的なようだ。例えばデータベース(MySQLなど)を利用する web アプリケーションであれば、つぎの3つのコンテナを立ち上げることになる:
当然、これらを連携するにはコンテナ間をまたいだ通信をする必要がある。Docker にはコンテナ間通信を実現するネットワーク機能が備わっていて、各コンテナは同じ(Docker の)ネットワークに接続していれば、コンテナ名とポート番号を使って通信することができる。
今日はそのコンテナ間通信を試してみる。
先日作った書籍管理 web アプリと、HTTP サーバとして Nginx を前に立てる構成とする。上にはデータベースサーバが書いてあるけど、この書籍管理アプリはデータベースに Sqlite を使っているので、今回データベースサーバはなし。アプリケーションサーバと HTTP サーバ(Nginx)の2つだ。
コンテナ名は、アプリケーションサーバを bruschetta-back、HTTP サーバを nginx-c とする。この2つが Docker ネットワークで通信するわけだ。nginx-c は80番ポートをホスト側の8080ポートに接続する。ホスト側からは bruschetta-d というホスト名で nginx-c にアクセスできるようにしておく。
先日作ったものなので詳細は省略。ただ、あいだに PC のリプレイスをはさんだので、イメージ名が bruschetta:1 に変わっている。内容は変更なし。
全面に立てる HTTP サーバには、Docker Hub で公開されている Nginx こイメージをメースにして、アプリケーションサーバにつなぐための設定ファイルをコピーしたものを用意する。
Dockerfile はこう:
ROM nginx:1.17.10 COPY ./files/bruschetta-d /etc/nginx/conf.d/bruschetta-d.conf RUN mkdir /var/log/nginx/bruschetta CMD [ "nginx", "-g", "daemon off;" ]
この中でコピーしている Nginx の仮想ホストの設定ファイルはこうだ:
upstream uwsgi-bruschetta { server bruschetta-back:5000; } server { # port listen 80; # server name server_name bruschetta-d; # log files access_log /var/log/nginx/bruschetta/access.log combined; error_log /var/log/nginx/bruschetta/error.log warn; keepalive_timeout 60; proxy_connect_timeout 60; proxy_read_timeout 60; proxy_send_timeout 60; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://uwsgi-bruschetta; } }
これで docker build
した。
できたイメージの状況。
akatoh@apostrophe:docker$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx-c 1 6f5be529ea6d About a minute ago 127MB bruschetta 1 11afb91367ae 2 hours ago 451MB nginx 1.17.10 9beeba249f3e 8 hours ago 127MB ubuntu 20.04 1d622ef86b13 3 weeks ago 73.9MB
Docker ネットワークの作成は docker network create
コマンドを利用する。
takatoh@apostrophe:docker$ docker network create nginx-network
これで nginx-network という名前の Docker ネットワークができた。つぎのようにすると様子が見える。
takatoh@apostrophe:docker$ docker network ls NETWORK ID NAME DRIVER SCOPE d0c23099f6be bridge bridge local 492e64e5d79d host host local 7f38bac647a0 nginx-network bridge local b42cbd843632 none null local
nginx-network 当名前が見える。ほかにもあるけど、これらはデフォルトで用意されているものらしい。詳細は調べてない。
2つのコンテナを起動する。その際、--netowork
オプションで接続する Docker ネットワークの名前(今回は nginx-network)を指定する。また、HTTP サーバのコンテナの方でアプリケーションサーバの名前を bruschetta-back と指定しているので、これを間違えないようにする。
まずはアプリケーションサーバのコンテナから。
takatoh@apostrophe:docker$ docker run --name bruschetta-back --network nginx-network -d bruschetta:1
HTTP サーバ。ポートの指定も忘れずに。
akatoh@apostrophe:docker$ docker run --name nginx-front --network nginx-network -p 8080:80 -d nginx-c:1
起動したコンテナは bruschetta-d というホスト名で待ち受けているので、/etc/hosts ファイルに 127.0.0.1 を指すように記述を追加する。それができたら準備は完了だ。http://bruschetta-d:8080/ にブラウザでアクセスしてみる。
結果、期待通りにアプリケーションにアクセス、使用できることが確認できた。
メインに使っている PC を買い替えた。
先日ダウンロードしておいた Ubuntu 20.04 LTS 日本語 Remix を DVD に焼いて(この作業は別の Windows マシンでやった)、プリインストールされていた Windows 10 は起動すらせずに上書きインストールした。ホスト名は替える前と同じ apostrophe。
OS のインストールが終わったら、とりあえずすぐに使いそうなソフトウェアだけインストールした。
Python はデフォルトで入っていた(コマンドとしては python3
)けど、今後を考えて pyenv を使った。Tweaks というのは、参考にした web ページにあった設定ツール。デスクトップまわりの設定ができる。
Docker についてはインストール方法を書いておこう。最初は先日 16.04 にインストールしたのを参考に作業をしたんだけどダメだった。えぇっ?と思いながらググってみると、apt
コマンドでインストールできるようになっていた。
takatoh@apostrophe:~$ sudo apt install -y docker.io takatoh@apostrophe:~$ sudo systemctl start docker takatoh@apostrophe:~$ sudo systemctl enable docker
ついでに docker-compose もインストール(今後使う予定なので)。
takatoh@apostrophe:~$ sudo apt install -y docker-compose
あとはいくつか設定をカスタマイズして、データをバックアップサーバからコピーしてきて、ひとまずは完了。のこりは必要に応じてやっていこう。
参考にしたページ: