コンテナ型仮想化
仮想化方式は3つに大別される云々の話はともかくとして、そもそもdockerとはその中でもコンテナ型仮想化と呼ばれる仮想化方式です。
ホストOS上でコンテナエンジン(docker)が動き、コンテナと呼ばれる仮想環境を管理します。
特徴としてはその他の仮想化方式のようにHWをエミュレートすることなく、リソースを共有するためオーバーヘッドが少なく動作が軽いこと。それでいてコンテナ間の独立性が高く、コンテナの作成・移植が容易な点などです。
例えば
dockerの用途はテスト用の環境構築や、そのまま本番環境として使われたりなど様々です。個人的には一度作った環境を残しておいたり、共有したりする際によく使います。最近じゃkurbenetesとかいうコンテナ群をリソースのように管理して、簡単にクラスタ化出来るものもあるそうな……
例えばWebサーバーを建てるとして、Apacheをインストールして、MySQLは5.7にして、phpは7.2で、index.phpを書いて、phpからMySQLに接続して、それからそれから……etcみたいな作業をオンプレであろうとクラウドであろうと行うと思います。
dockerではこれらの作業をコマンド一つで出来て、更にGitHubやdockerhubで共有する事も可能になります。
docker-composeとdockerfile
dockerではosイメージをgitなどからダウンロードしてきて、それを元にコンテナと呼ばれる独立した仮想環境を作っていきます。
これを自動化するための手順書がdockerfileです。docker-composeは複数コンテナ用だと思ってください。
今回はLAMP環境を構築するdocker-composeを作っていきます。
階層
apache_mysql/
|-- docker
| `-- db
| |-- data
| |-- my.cnf
| `-- sql
| |-- 001-create-tables.sql
| `-- init-database.sh
|-- docker-compose.yml
|-- php
| |-- Dockerfile
| `-- index.php
`-- README.md
docker-compose.yml
version: '2'
services:
# php:apache
app:
build:
context: ./php
dockerfile: Dockerfile
container_name: php_apa
# :zを付与することでコンテナにマウントされたボリュームにラベル付けを行う(SELinux避け)
volumes:
- ./php:/var/www/html:z
ports:
- 80:80
depends_on:
- db
links:
- db:mysql
# MySQL
db:
image: mysql:5.7
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: test_db
MYSQL_USER: root
MYSQL_PASSWORD: password
TZ: 'Asiz/Tokyo'
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./docker/db/data:/var/lib/mysql:z
- ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf:z
- ./docker/db/sql:/docker-entrypoint-initdb.d:z
ports:
- 3306:3306
上のdocker-compose.ymlを後述のコマンドの引数に渡して実行すると、それぞれのDockerfileを実行して、apacheコンテナとmysqlコンテナを作成します。
apacheから
php/Dockerfile
FROM php:7.2-apache
RUN docker-php-ext-install pdo_mysql
php/index.php
<html>
<table>
<tr>
<th>id</th>
<th>title</th>
<th>pagenum</th>
</tr>
<?php
/**********************************/
/* DB諸情報 */
/* コンテナから見えるホスト名を設定 */
/* ホスト名にはコンテナ名 */
/**********************************/
define('DB_DATABASE', 'test_db');
define('DB_USERNAME', 'root');
define('DB_PASSWORD', 'password');
define('PDO_DSN', 'mysql:host=b4da929b46b0;dbname=' . DB_DATABASE);
$sql = 'SELECT * from master_table';
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$arr = $db->query($sql, PDO::FETCH_ASSOC);
foreach($arr as $que_res) {
if ($que_res === reset($arr)) {
echo "<tr>";
}
echo "<td>", $que_res['id'], "</td><td>", $que_res['title'], "</td><td>", $que_res['pagenum'], "</td>";
if ($que_res === end($arr)) {
echo "</tr>";
}
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
?>
</table>
</html>
id | title | pagenum |
“, $que_res[‘id’], “ | “, $que_res[‘title’], “ | “, $que_res[‘pagenum’], “ |
mysql:host=834b7aa1babf;の箇所に関してですが、これはmysqlのコンテナ名をホスト名にしています。
ifconfigとかで見えるホスト名と、コンテナ間で解決されるホスト名に差異があるらしく、この様な措置をとりました。
多分これも自動化する方法はあると思われます。
MySQL
sql/init-database.sh
#!/usr/bin/env bash
mysql -u root -ppassword test_db < "/docker-entrypoint-initdb.d/001-create-tables.sql"
この辺もdocker-composeに載せれるはずなんだけど、とりあえず起動後に手打ちでお願いします。
sql/001-create-tables.sql
---- create ----
CREATE DATABASE IF NOT EXISTS test_db;
DROP TABLE IF EXISTS master_table;
create table master_table
(
id INT(20) AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(100),
artist VARCHAR(50),
pagenum INT(11),
category VARCHAR(100),
tag VARCHAR(100),
etc VARCHAR(100),
uploadtime VARCHAR(100)
) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
---- insert ----
START TRANSACTION;
insert into master_table (title, uploadtime, pagenum) value ('バッテリー', '2019-09-23 19:44:46', 36);
COMMIT;
dataディレクトリはdbの諸情報が勝手に入るディレクトリです。
起動
docker-composeをインストールして下記コマンドを実行します。
# docker-compose.ymlがあるディレクトリへ移動
$ docker-compose up -d
先述の設定フローには起動後の作業も含まれているので、全自動とまではいかないのですが(自分の勉強不足)、それでも十分強力です。