[Docker] コマンドの実行

コマンドの実行系統の命令は「RUN」「CMDとENTRYPOINT」の2種類ある
前者はイメージ作成時、後者はコマンドの実行時

### RUN
RUNコマンドはdocker buildするタイミング
(1)シェル形式
/bin/sh -cを経由してコマンドが実行
RUN ${コマンド} ${引数} …

(2)exec形式
実行したいコマンドや引数を[]を囲んで記述
RUN [“コマンド”, “引数”, …]

RUNコマンドごとにレイヤーが増えるので、一つのコマンドで実現できる様にする
RUN コマンド1 && コマンド2 && コマンド3

ONBUILD COPY コピー元 コピー先

### CMDとENTRY POINT
コンテナを起動したときのタイミングでコンテナの中で実行するコマンドを指定する
(1)ENTRY POINT: コマンドの指定を強要する。イメージの利用者はこの設定を変更することはできない。
docker runの最後に指定するコマンドは、ENTRYPOINTで指定したコマンドへの引数となる

(2)CMD
docker runの際に指定する最後のコマンドのデフォルト値を変更

殆どの場合、CMDが使われる
イメージが通信しようとするポート番号はEXPOSEで指定する

### HTTPDのDockerfile
https://github.com/docker-library/httpd/blob/master/2.4/Dockerfile

phpimage/index.php

<body>
	Your IP <?php echo $_SERVER['REMOTE_ADDR']; ?>。
</body>

Dockerfile

FROM debian
EXPOSE 80
RUN apt update \
&& apt install -y apache2 php libapache2-mod-php \
&& apt clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm /var/www/html/index.html
COPY index.php /var/www/html
CMD /usr/sbin/apachectl -DFOREGROUND

apt clean, rm -rf /var/lib/apt/lists/* でパッケージを削除する。常套句。
中間ファイルを削除することで、Dockerイメージのサイズを小さくできる
CMD /usr/sbin/apachectl -DFOREGROUND でapacheをフォアグラウンドで実行する

$ sudo docker build . -t myphpimage
$ sudo docker images;
REPOSITORY TAG IMAGE ID CREATED SIZE
myphpimage latest 5c4aa75b77ce 4 minutes ago 254MB

– コンテナを動かす
$ sudo docker run -dit –name myphp -p 8080:80 myphpimage

キャッシュを活用するとビルドを高速化できる
キャッシュを使わない場合は、docker build . -t myphpimage –no-cache とする

なるほど、Dockerfileの作成は練習が必要だな…

[Docker] fileのbuild

Dockerfile

FROM httpd
COPY index.html /usr/local/apache2/htdocs/

1行目はFROM命令
「#」はコメント
行を跨ぐときは末尾に「¥」を記述
「${環境変数}」は環境変数

index.html

<body>
	<h1>Docker Test</h1>
</body>

### イメージをビルド
$ sudo docker build -t myimage01 .
$ sudo docker images;
REPOSITORY TAG IMAGE ID CREATED SIZE
myimage01 latest b2397acb1a5a 43 seconds ago 144MB
$ sudo docker history myimage01;
IMAGE CREATED CREATED BY SIZE COMMENT
b2397acb1a5a About a minute ago /bin/sh -c #(nop) COPY file:752610804eacad0e… 213B

$ sudo docker run -dit –name webcontent_docker -p 8080:80 myimage01
7528440013bfa467f5e06d4f4a0b3eec0182ae5bb433d6045ee52611119f2b7c

http://192.168.56.10:8080/

なるほどー

### Dockerfileのコマンド
FROM
ベースイメージを指定する
ADD
イメージにファイルやフォルダを追加する。Dockerfileを置いたディレクトリ外のリモートファイルも指定できる。圧縮ファイルを指定したときは自動的に展開される。
COPY
イメージにファイルやフォルダを追加する。Dockerfileを置いたディレクトリ内のファイルしか指定できない。圧縮ファイルを指定したときは、圧縮ファイルのままコピーされる。
RUN
イメージをビルドするときにコマンドを実行する。
CMD
コンテナを起動するときに実行する既定のコマンド(docker createやdocker runで実行するコマンドを省略したとき)を指定する
ENTRYPOINT
イメージを実行するとき(docker createやdocker runするとき)のコマンドを強要する
ONBUILD
ビルド完了したときに任意の命令を実行する
EXPOSE
通信を想定するポートをイメージの利用者に伝える
ONBUILD
ビルドが完了したときに任意の命令を実行する
EXPOSE
通信を想定するポートをイメージの利用者に伝える
VOLUME
永続データが保存される場所をイメージの利用者に伝える
ENV
環境変数を定義する
WORKDIR
RUN, CMD, ENTRYPOINT, ADD, COPYの際の作業ディレクトリを指定する
SHELL
ビルド時のシェルを指定する
LABEL
名前やバージョン番号、制作者情報などを設定する
USER
RUN、CMD、ENTRYPOINTで指定するコマンドを実行するユーザやグループを設定する(USERを指定しない場合はroot)
ARG
docker buildする際に指定できる引数を宣言する
STOPSIGNAL
docker stopする際に、コンテナで実行しているプログラムに対して送信するシグナルを変更する(規定は)
HEALTHCHECK
コンテナの死活確認をするヘルスチェックの方法をカスタマイズする

[CakePHP4.x] 3系との違いを考える

$ php composer.phar create-project –prefer-dist cakephp/app:4.* blog
$ bin/cake server -H 192.168.56.10 -p 8000
$ bin/cake migrations migrate

migrations migrate
migrations migrate -t migrationID
migrations rollback
migrations rollback -t migrationID
migrations status

PostsTable.php

    public function validationDefault(Validator $validator): Validator
    {
        $validator
            ->integer('id')
            ->allowEmptyString('id', null, 'create');

        $validator
            ->scalar('title')
            ->maxLength('title', 150, '150文字以上で入力してください。')
            ->minLength('title', 5, '5文字以上で入力してください。')
            ->notEmptyString('title', 'タイトルは必ず入力してください');

        $validator
            ->scalar('description')
            ->maxLength('description', 255, '150文字以上で入力してください。')
            ->allowEmptyString('description');

        $validator
            ->scalar('body')
            ->allowEmptyString('body');

        $validator
            ->boolean('published')
            ->notEmptyString('published');

        return $validator;
    }

OK、続いて、デプロイ周りか…

[CakePHP] 3.xの復習

– データベースの作成から(mysql)
create database cake3
use cake3

create table posts (
id int unsigned auto_increment primary key,
title varchar(255),
body text,
created datetime default null,
modified datetime default null
);
insert into posts (title, body, created) values
(‘title 1’, ‘body 1’, now()),
(‘title 2’, ‘body 2’, now()),
(‘title 3’, ‘body 3’, now());
select * from posts;

– cakephpのインストール
composerでインストールする
$ php composer.phar create-project –prefer-dist cakephp/app:3.* myapp

### ディレクトリ構成の変更
– srcフォルダ新設
– webrootがWebブラウザからアクセスしたときに見るフォルダ

### 2系と3系の違い
1
ディレクトリ構成の変更
app, lib, plugins, vendors
bin, config, plugins, src, tests, tmp, vendor, webroot
-srcの中に、controller, model viewが入る
-webrootにpublicなファイルを配置
2
intl拡張モジュール
不要
必要
php-intlインストール
2
ビルトインサーバー
なし
bin/cake server -H 192.168.56.10 -p 8000

3
データベースの設定
app/Config/database.php
config/app.php

4
タイムゾーンの設定
app/Config/core.php
config/app.php

5
MVCファイルの作成
手動
bin/cake bake all ${app}

6
Modelファイル
app/Model/Post.php
src/Model/Table/PostsTable.php

7
Modelの書き方
class Post extends AppModel{
}
name space App\Model\Table
use Cake\ORM\Table;
class PostsTable extends Table{
}
名前空間を定義
ORM, Validation等を使用
Classの中にinitializeで初期化
8
Viewファイル
app/View/Posts/index.ctp
src/Template/Posts/index.ctp
titleなどはviewの中に記載
elementを追加できる
9
Controllerファイル
app/Controller/PostsController.php
src/Controller/PostsController.php

10
Controllerの書き方

namespace App\Controller;
class PostsController extends AppController { 
}
レコードの作成は$this->Posts->newEntity();と書く
11
Controllerでのfindの書き方
$this->Post->find(‘all’, $params);
$this->Post->find(‘all’)->order([‘title’=>’DESC’]);
繋げて条件を指定できる
12
Routing
app/Config/routes.php
config/routes.php

13
Template
app/View/Layouts/default.ctp
src/Template/Layout/default.ctp
controllerに$this->viewBuilder()->layout(‘my_layout‘);で独自テンプレートを表示できる
14
Validation
modelでarrayで定義
modelでValidationDefaultで定義

うーむ、これ3系と4系の違いもやらんといけんのか…

[CakePHP] 2.xの復習

公式サイト
https://cakephp.org/jp
ドキュメント
https://book.cakephp.org/4/ja/index.html

PHP/MySQL/HTMLCSSJS

– 覚えておいた方が良い用語
MVC -> Model, View, Controller
CoC: Convention over Configuration

CakePHP 2.xをインストールしようと思ったが…
$ git clone -b 2.x git://github.com/cakephp/cakephp.git
Cloning into ‘cakephp’…
fatal: remote error:

composerで入れるか…
$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar create-project –prefer-dist ‘cakephp/app:2.10.*’ myapp
Creating a “cakephp/app:2.10.*” project at “./myapp”

[InvalidArgumentException]
Could not find package cakephp/app with version 2.10.*.

composerでももはや無理なので、githubから無理やり取得します
https://github.com/cakephp/cakephp/tree/2.10.22

ここまででそこそこ時間がかかってしまった…orz
$ cd cakephp-2.10.22

appを使う
controller, model, view

書き込み権限
$ sudo chown -R vagrant app/tmp/

create table posts(
id int not null auto_increment primary key,
title varchar(50),
body text,
created datetime default null,
modified datetime default null
);

insert into posts (title, body, created, modified) values
(‘title 1’, ‘body 1’, now(), now()),
(‘title 2’, ‘body 2’, now(), now()),
(‘title 3’, ‘body 3’, now(), now());

Model/Post.php

class Post extends AppModel {
	
}

Controller/PostsController.php

class PostsController extends AppController {

	public $helpers = array('Html', 'Form');

	public function index(){
		$params = array (
			'order' => 'modified desc',
			'limit' => 2
		);
		$this->set('posts', $this->Post->find('all', $params));
		$this->set('title', '記事一覧');
	}
}

/View/posts/index.ctp

<h2></h2>

<ul>
<?php foreach ($posts as $post) : ?>
<li>
<?php
// debug($post);
echo h($post['Post']['title']);
?>
</li>
<?php endforeach; ?>
</ul>

config/core.php

	Configure::write('debug', 0);

config/routes.php

	Router::connect('/', array('controller' => 'posts', 'action' => 'index'));

View/Layouts/default.ctp
-> templateが書かれている

URL -> /${controller}/${method}/

postscontroller.php

	public function view($id = null){
		$this->Post->id = $id;
		$this->set('post', $this->Post->read());
	}

/View/posts/view.ctp

<h2><?php echo h($post['Post']['title']); ?></h2>

<p><?php echo h($post['Post']['body']); ?></p>

index.ctp

echo $this->Html->link($post['Post']['title'], '/posts/view/'.$post['Post']['id']);

<h2>Add Post</h2>
<?php echo $this->Html->link('Add post', array('controller'=>'posts', 'action'=>'add')); ?>

add.ctp

<h2>Add post</h2>

<?php
echo $this->Form->create('Post');

echo $this->Form->input('title');
echo $this->Form->input('body', array('rows'=>3));
echo $this->Form->end('Save Post');
?>

エラーチェックはmodelにvalidationを書いていく
Mode/Post.php

class Post extends AppModel {
	public $validate = array(
		'title' => array(
			'rule' => 'notEmpty',
		),
		'body' => array(
			'rule' => 'notEmpty',
		)
	);
}

Posts/edit.ctp

<h2>Edit Post</h2>

<?php
echo $this->Form->create('Post'. array('action'=>'edit'));

echo $this->Form->input('title');
echo $this->Form->input('body', array('rows'=>3));
echo $this->Form->end('Save!');

2系はかなり古いか…
Cake自体があまり人気ないかも…

Event BridgeでAWS Batchを動かしたい

5分おきの場合は
0/5 * ? * * * で設定する。Day of monthが?になるのは何故かわからん。

次の画面で、targetに Batch job queueを選択する
job queue, job definitionはarn, job nameは任意に入れる

Ruleができたら、cloud watchで確認する

うん、event bridgeからも実行できているのがわかります。

[AWS Batch] 触って理解する

### 機能の流れ
Batchで実行したい処理を定義する(自動的にECSにクラスタが作られる)
-> Batchで処理を走らせる(EC2にインスタンスが立ち上がり、処理が完了したら自動でインスタンスが削除される)
– CloudWatch内のイベント機能で定期実行するようにする

1. Job definitionsでジョブを定義する
– platform: fargate, ecsTaskExecutionRole
– Job configuration: public.ecr.aws/amazonlinux/amazonlinux:latest
L Command syntax: Bash
L Command: echo ‘hello world

2. Compute environments 作成

3. test_job_queues作成

4. Jobsを作成

CannotPullContainerError: inspect image has been retried 5 time(s): failed to resolve ref “public.ecr.aws/amazonlinux/amazonlinux:latest”: failed to do request: Head https://public.ecr.aws/v2/amazonlinux/amazonlinux/manifests/latest: dial tcp 99.83.145…

うーん、うまくいかんな…

CannotPullContainerError: inspect image has been retried 5 time(s): failed to resolve ref “docker.io/library/busybox:latest”: failed to do request:

インターネットゲートウェイは設定されてると思うんだが...

色々試した結果、Assign public IPがENABLEDだと上手くいった
cloudwatch logsの /aws/batch/job で確認した結果

んで、これをcloudwatch eventsで実行させたい

[Docker] コンテンツ入りのhttpdコンテナを作る

1. httpdコンテナを起動する
$ sudo docker run -dit –name webcontent -p 8080:80 httpd:2.4
$ sudo docker cp tmp/index.html webcontent:/usr/local/apache2/htdocs

2. コンテナをイメージ化する
docker commitコマンドを使う
$ sudo docker commit webcontent mycustomed_httpd
$ sudo docker images;
REPOSITORY TAG IMAGE ID CREATED SIZE
mycustomed_httpd latest 3239a258d78d 10 seconds ago 144MB
$ sudo docker image history mycustomed_httpd
IMAGE CREATED CREATED BY SIZE COMMENT
3239a258d78d About a minute ago httpd-foreground 219B
b9bd7e513e0f 3 days ago /bin/sh -c #(nop) CMD [“httpd-foreground”] 0B
3 days ago /bin/sh -c #(nop) EXPOSE 80 0B

3. カスタムなイメージを使う
$ sudo docker run -dit –name webcontent_new -p 8081:80 mycustomed_httpd
$ sudo docker ps
$ sudo docker exec -it webcontent_new /bin/bash
root@6bbe9d0c262d:/usr/local/apache2# cat /usr/local/apache2/htdocs/index.html

4. 後始末
$ sudo docker stop webcontent webcontent_new
$ sudo docker rm webcontent webcontent_new
$ sudo docker rmi mycustomed_httpd

ニャルほどー
3連休、こればっかりやってるけど、進んでる感じがしないなー
まあ、理解はかなり進んだが…

[Docker] イメージの自作

httpdイメージには、PHPをインストールするためのパッケージやビルドするための環境などが含まれていない

### よく使われるベースイメージ
debian: なんでもしたいときはdebianが多い
ubuntu: ubuntuフルセット
alpine: muslとBusyBoxをベース パッケージマネージャが付属しているため、busyboxよりこちらの方が使い勝手が良い
busybox: 組み込み目的で作られた小さいLinux

※2.4-alpineなどはalpineをベースに作られたもの
Linuxカーネルは、その下で動いているUbuntuのものなどが使われる。コンテナの中にカーネルはない

– レイヤーの確認(mysqlのレイヤーを確認する)
$ sudo docker image rm mysql:5.7
$ sudo docker pull mysql:5.7
5.7: Pulling from library/mysql
a4b007099961: Pull complete
e2b610d88fd9: Pull complete
38567843b438: Pull complete
5fc423bf9558: Pull complete
aa8241dfe828: Pull complete
cc662311610e: Pull complete

「a4b007…」「e2b610…」「38567…」がレイヤーに相当するイメージ

– Dockerの流儀に従って作る
Dockerfileのベストプラクティス
https://docs.docker.jp/engine/articles/dockerfile_best-practice.html
– 1つのコンテナは1つの処理しかしない
– 利用するポートを明確にする
– 永続化すべき場所を明確にする
– 設定は環境変数で渡す
– ログは標準出力に書き出す
– メインプログラムが終了するとコンテナが終了

ベースイメージに何を使うべきなのかずっと疑問だったが、ある程度理解できた。
バッチのところがやや課題か…

[Docker] Docker Composeの仕組み

Docker Composeは、あらかじめコンテナの起動方法やボリューム、ネットワーク構成などを書いた定義ファイルを用意しておき、その定義ファイルっを読み込ませることでまとめて実行する方法
Docker ComposeはPython製のツール

$ sudo docker-compose –version

docker-compose.yml

version: '3'

services:
  wordpress-db:
    image: mysql:5.7
    networks:
      - wordpressnet
    volumes:
      - wordpress_db_volume:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: myrootpassword
      MYSQL_DATABASE: wordpressdb
      MYSQL_USER: wordpressuser
      MYSQL_PASSWORD: wordpresspass

  wordpress-app:
    depends_on:
      - wordpress-db
    image: wordpress
    networks:
      - wordpressnet
    ports:
      - 8080:80
    restart: always
    environment:
      WORDPRESS_DB_HOST: wordpress-db
      WORDPRESS_DB_NAME: wordpressdb
      WORDPRESS_DB_USER: wordpressuser
      WORDPRESS_DB_PASSWORD: wordpresspass

networks:
  wordpressnet:

volumes:
  wordpress_db_volume:

### Docker Compose操作
$ sudo docker-compose up -d
$ sudo docker-compose ps
Name Command State Ports
———————————————————————————————————
wordpress_wordpress-app_1 docker-entrypoint.sh apach … Up 0.0.0.0:8080->80/tcp,:::8080->80/tcp
wordpress_wordpress-db_1 docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
$ sudo docker network ls
$ sudo docker volume ls

### コンテナを停止して破棄
$ sudo docker-compose down

### Docker-compose.ymlの書き方
1. サービス
2. ネットワーク
3. ボリューム

image:wordpress
image:
wordpress
depends_on: この定義によって、後に起動できる

– ネットワークの指定省略
明示的にネットワークを指定しなかったときは、記述しているサービスが繋がるDockerネットワークを自動的に作成し、全てのサービスをそのネットワークに接続するように構成する

– サービスを個別に操作
docker-compose logs
docker-compose rm
docker-compose run
docker-compose exec
docker-compose start
docker-compose stop

うむー進むのだけは早い