Dockerでlaravel 6.x用のAmazonLinux2コンテナを作りたい

1. Docker hubからAmazon Linux 2をpullする
$ sudo docker pull amazonlinux:2
$ sudo docker images
2. コンテナにログイン
$ sudo docker run -i -t 484 /bin/bash
bash-4.2# cat /etc/system-release
Amazon Linux release 2 (Karoo)

### git install
$ yum update
$ yum -y install gcc curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker autoconf
$ wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.19.2.tar.gz
bash: wget: command not found
あら?
$ yum install wget
$ wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.19.2.tar.gz
$ tar xzvf git-2.19.2.tar.gz
bash: tar: command not found
ありゃ
$ yum install tar
$ tar xzvf git-2.19.2.tar.gz
$ rm -rf git-2.19.2.tar.gz
$ cd git-2.19.2
$ make prefix=/usr/local all
bash: make: command not found
なにーーーーーーーーーーーーーーーー
$ yum install make
$ make prefix=/usr/local all
$ make prefix=/usr/local install
$ git –version

### Node.js install
// 省略

### httpd install
$ yum install httpd
$ systemctl start httpd
Failed to get D-Bus connection: Operation not permitted

原因

・—privilegedを使用
・/sbin/initで起動
・上記に合わせ、-itではなく-dで起動し、起動後にexec

$ sudo docker run -d –privileged –name amzn2 amazonlinux:2 /sbin/init
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused “exec: \”/sbin/init\”: stat /sbin/init: no such file or directory”: unknown.
amazonlinux2には/sbin/initがないとのこと

$ sudo docker exec -it amzn2 /bin/bash
$ yum install systemd-sysv
$ exit

$ sudo docker commit c922 amzn:2
$ docker run -d –privileged –name amzn amzn:2 /sbin/init
$ sudo docker exec -it amzn /bin/bash
$ systemctl start httpd
$ systemctl enable httpd

### PHP 7.3
### Ansible
// 省略

### docker commit & push
$ sudo docker commit ${containerId} {DockerName}/amzn
$ sudo docker login
$ sudo docker push ddddocker/amzn
The push refers to repository [docker.io/ddddocker/amzn]
7a035032cdab: Pushing 53.97MB/2.934GB
4948e9de7aa2: Pushing 46.8MB/1.031GB
あれ、3GB? こりゃあかんわ。

$ sudo docker history ddddocker/amzn
IMAGE CREATED CREATED BY SIZE COMMENT
1530f5eb21ed 8 minutes ago /sbin/init 2.93GB
558083a921e9 3 hours ago /bin/bash 1.03GB
484b3aa1f601 3 weeks ago /bin/sh -c #(nop) CMD [“/bin/bash”] 0B
3 weeks ago /bin/sh -c #(nop) ADD file:c43f05fa78d78f998… 163MB

こりゃあかん。こんなにdisk sizeが増えるとは思わなかった。
installしたimageをrepoから取得するのではなく、docker-composeでamazonlinux2をpullして、それからinstallするフローに変えた方が良さそうですね。

dockerでのLaravel環境構築を考える

まず、laradockなどのdocker-compose.ymlの中身を見てみます。

Laradock:http://laradock.io/
ucan-lab: ucan-lab docker laravel

$ git clone https://github.com/ucan-lab/docker-laravel.git

version: "3"
services:
  app:
    build:
      context: ./docker/php
      args:
        - TZ=${TZ:-Asia/Tokyo}
    ports:
      - ${APP_PORT:-18000}:8000
    volumes:
      - ${PROJECT_PATH:-./src}:/work
      - ./docker/ash:/etc/profile.d
      - ./docker/php/psysh:/root/.config/psysh
      - ./logs:/var/log/php
      - ./docker/php/php.ini:/usr/local/etc/php/php.ini
    working_dir: /work
    environment:
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_DATABASE=${DB_NAME:-homestead}
      - DB_USERNAME=${DB_USER:-homestead}
      - DB_PASSWORD=${DB_PASS:-secret}
      - TZ=${TZ:-Asia/Tokyo}
      - MAIL_HOST=${MAIL_HOST:-mail}
      - MAIL_PORT=${MAIL_PORT:-1025}
      - CACHE_DRIVER=redis
      - SESSION_DRIVER=redis
      - QUEUE_DRIVER=redis
      - REDIS_HOST=redis

  web:
    image: nginx:1.17-alpine
    depends_on:
      - app
    ports:
      - ${WEB_PORT:-10080}:80
    volumes:
      - ${PROJECT_PATH:-./src}:/work
      - ./logs:/var/log/nginx
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    environment:
      - TZ=${TZ:-Asia/Tokyo}

  db:
    image: mysql:8.0
    volumes:
      - db-store:/var/lib/mysql
      - ./logs:/var/log/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    environment:
      - MYSQL_DATABASE=${DB_NAME:-homestead}
      - MYSQL_USER=${DB_USER:-homestead}
      - MYSQL_PASSWORD=${DB_PASS:-secret}
      - MYSQL_ROOT_PASSWORD=${DB_PASS:-secret}
      - TZ=${TZ:-Asia/Tokyo}
    ports:
      - ${DB_PORT:-13306}:3306

  db-testing:
    image: mysql:8.0
    volumes:
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    tmpfs:
      - /var/lib/mysql
      - /var/log/mysql
    environment:
      - MYSQL_DATABASE=${DB_NAME:-homestead}
      - MYSQL_USER=${DB_USER:-homestead}
      - MYSQL_PASSWORD=${DB_PASS:-secret}
      - MYSQL_ROOT_PASSWORD=${DB_PASS:-secret}
      - TZ=${TZ:-Asia/Tokyo}
    ports:
      - ${DB_TESTING_PORT:-13307}:3306

  node:
    image: node:12.14-alpine
    tty: true
    volumes:
      - ${PROJECT_PATH:-./src}:/work
    working_dir: /work

  redis:
    image: redis:5.0-alpine
    volumes:
      - redis-store:/data

  mail:
    image: mailhog/mailhog
    ports:
      - ${MAILHOG_PORT:-18025}:8025

volumes:
  db-store:
  redis-store:

何故かdockerだと、何故か皆apacheではなくnginxを採用しています。何故なんでしょう。

そしてLaradockの仕様を見ると、コンテナに入ってcreate projectして、ローカルにファイルを同期させて編集しているように見えますね。
VagrantやEC2での初期のapache、PHP、node、ansible等のインストール部分をまとめたimageとmysqlのimageからコンテナ起動するイメージだったので、なんか違うような。。

docker-compose.ymlの使い方

– Docker Compose: Dockerイメージのビルドや各コンテナの起動・停止をより簡単に行えるようにするツール
– Dockerビルドやコンテナ起動のオプションなどを含め、複数のコンテナの定義をymlファイルに書き、それを利用してDockerビルドやコンテナ起動をする

### Docker Composer install
$ sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose –version
docker-compose version 1.21.2, build a133471

docker-compose.ymlが必要になる
– Dockerイメージをビルドするための情報
– コンテナ起動するための情報
– 使用するDockerネットワーク

docker-compose.yml

version: '3'
services:

  wordpress:
    image: wordpress
    container_name: some-wordpress
    restart: unless-stopped
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_PASSWORD: my-secret-pw

  mysql:
    image: mysql:5.7
    container_name: some-mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: my-secret-pw
    ports: 
      - "3306:3306"

docker-composeを使用すると、自動でDockerネットワークを作成する

### docker-compose.ymlの起動
$ sudo docker-compose up -d
//停止
$ sudo docker-compose stop

$ sudo docker exec -it 5d7 bash
$ cat wp-config.php

$ sudo docker exec -it b1f bash
# mysql -u root -p
ERROR 1045 (28000): Access denied for user ‘root’@’localhost’ (using password: YES)

あれ、MySQLにログインできない

https://github.com/docker-library/mysql/issues/180

Are you mapping to an existing database or creating a new one?
The root password variable will only be used when creating a database. It won't change the root password of an existing one.

docker stop, docker rmして、再度docker-compose up -d
http://192.168.33.10:8080/

docker-composeとコンテナ間通信の仕組みが分かりました。

Dockerのコンテナ間通信

一つのコンテナでは一つの機能を動かす構成にする場合が多い
コンテナ間での通信が必要になる

### コンテナ間通信
1. Dockerネットワークを作成してコンテナ名で接続できるようにする
2. 「–link」オプションを使用する

### Dockerネットワークの作成
Dockerネットワークを作成してコンテナ間通信できるようにする
$ sudo docker network create wordpress-network
$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
31273346499c bridge bridge local
4871671c00c4 host host local
a83a0f7dda37 none null local
947b80aea44c wordpress-network bridge local
※bridgeネットワークはDNS設定がされていないため、名前解決ができずネットワーク通信ができない。
// Dockerネットワーク詳細
$ sudo docker network inspect wordpress-network

### ネットワークを指定してコンテナを起動
// mysql5.7
$ sudo docker run –name mysql –network wordpress-network -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7
// wordpress
$ sudo docker run –name wordpress –network wordpress-network -e WORDPRESS_DB_PASSWORD=my-secret-pw -p 8080:80 -d wordpress
http://192.168.33.10:8080/wp-admin/install.php

※MySQLのコンテナに接続できるようにするためには
$ sudo docker run –name mysql –network wordpress-network -p 13306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7

「–link」オプションはレガシー機能
sudo docker run –name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7
sudo docker run –name some-wordpress -e WORDPRESS_DB_PASSWORD=my-secret-pw –link some-mysql:mysql -d -p 8080:80 wordpress

### Nginx、Tomcatコンテナでのコンテナ間通信
$ mkdir tutorial
$ cd tutorial
$ mkdir nginx
$ mkdir tomcat
$ cd nginx
$ sudo vi Dockerfile

FROM nginx:latest

RUN rm -f /etc/nginx/conf.d/default.conf
COPY ./files/tomcat.conf /etc/nginx/conf.d/

$ mkdir files
$ cd files
$ sudo vi tomcat.conf

server {
    location /tomcat/ {
         proxy_pass http://tomcat-1:8080/;
    }
}

// Nginxイメージ作成
$ cd ..
$ sudo docker build -t nginx-tomcat:1 .

### Docker network作成、コンテナ起動
$ sudo docker network create tomcat-network
$ sudo docker rm 5093
$ sudo docker run –name tomcat-1 –network tomcat-network -d tomcat:1
$ sudo docker run –name nginx-tomcat-1 –network tomcat-network -p 10080:80 -d nginx-tomcat:1
http://192.168.33.10:10080/tomcat/

Dockerfileの書き方

### Dockerfileの作成
$ ls
apache-tomcat-9.0.31.tar.gz Dockerfile
$ mkdir files
$ cp apache-tomcat-9.0.31.tar.gz files/

$ sudo vi Dockerfile

FROM centos:7 # ベースとなるdocker image
RUN yum install -y java # runはosコマンド
ADD files/apache-tomcat-9.0.31.tar.gz /opt/ # ADDはコンテナへのコピーとtar展開
CMD [ "/opt/apache-tomcat-9.0.31/bin/catalina.sh", "run"] #CMDはコンテナ起動時に実行

### docker build & run
$ sudo docker images
// docker build -t
$ sudo docker build -t tomcat:1 .
$ sudo docker images
$ docker run -it -d –name
$ sudo docker run -it -d –name tomcat-1 -p 8081:8080 tomcat:1
http://192.168.33.10:8081/
// log確認
$ sudo docker logs -f tomcat-1

docker imageを作成する手順

### UbuntuにCentos7をpull
$ sudo docker pull centos:7
$ sudo mkdir -p /root/tomcat-container/logs
// 「-p」オプションでポートフォワード設定、「-v」オプションでhostとコンテナのディレクトリを共有
$ sudo docker run -it -d -p 18080:8080 -v /root/tomcat-container/logs:/share/logs –name tomcat centos:7
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
beba506d8248 centos:7 “/bin/bash” 18 minutes ago Up 18 minutes 0.0.0.0:18080->8080/tcp tomcat

### tomcat download
// Tomcat 9.0.31 download https://tomcat.apache.org/download-90.cgi#9.0.31
$ wget http://www-eu.apache.org/dist/tomcat/tomcat-9/v9.0.31/bin/apache-tomcat-9.0.31.tar.gz
// docker cp :
$ sudo docker cp apache-tomcat-9.0.31.tar.gz tomcat:/opt/

### コンテナ側での作業
// container login
$ sudo docker exec -it tomcat bash
// java install
$ yum install -y java
$ cd /opt/
$ tar zxf apache-tomcat-9.0.31.tar.gz
$ ls
$ cd apache-tomcat-9.0.31
$ ls
$ ./bin/startup.sh

### ログの出力先変更
$ sed -i -e “s/\${catalina.base}\/logs/\/share\/logs/g” ./conf/logging.properties
$ ./bin/shutdown.sh
$ ./bin/startup.sh
$ ls -la /share/logs/
// ubuntu側にログが共有されている
$ sudo ls -la /root/tomcat-container/logs/
total 20
drwxr-xr-x 2 root root 4096 Mar 16 13:29 .
drwxr-xr-x 3 root root 4096 Mar 16 11:55 ..
-rw-r—– 1 root root 5890 Mar 16 13:29 catalina.2020-03-16.log
-rw-r—– 1 root root 0 Mar 16 13:29 host-manager.2020-03-16.log
-rw-r—– 1 root root 408 Mar 16 13:29 localhost.2020-03-16.log
-rw-r—– 1 root root 0 Mar 16 13:29 manager.2020-03-16.log
$ sudo docker stop tomcat
$ sudo docker ps -a
$ sudo ls -la /root/tomcat-container/logs/

### Docker image作成
// docker commit
$ sudo docker commit tomcat tomcat-image
$ sudo docker images

### 作成したDocker imageからコンテナ起動(上記の複製)
$ sudo mkdir -p /root/tomcat-container/logs2
$ sudo docker run -it -d -p 18082:8080 -v /root/tomcat-container/logs2:/share/logs –name tomcat2 tomcat-image
$ sudo docker ps -a
$ sudo docker exec -it tomcat2 bash
$ ls /opt
$ cd /opt/apache-tomcat-9.0.31
$ ./bin/startup.sh
http://192.168.33.10:18082/
$ exit
$ sudo docker stop tomcat2

繰り返しやることで、少しずつ慣れてきます。

Dockerの基本操作

### Ubuntu/trustyにdockerインストール済
$ sudo docker version
Client:
Version: 18.06.3-ce
API version: 1.38
Go version: go1.10.3
Git commit: d7080c1
Built: Wed Feb 20 02:27:13 2019
OS/Arch: linux/amd64
Experimental: false

Server:
Engine:
Version: 18.06.3-ce
API version: 1.38 (minimum version 1.12)
Go version: go1.10.3
Git commit: d7080c1
Built: Wed Feb 20 02:25:38 2019
OS/Arch: linux/amd64
Experimental: false
// 動作テスト
$ sudo docker run –name some-nginx -d -p 8080:80 nginx

### image一覧表示
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 6678c7c2e56c 11 days ago 127MB

### Dockerコンテナ一覧
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
615c9946da6d nginx “nginx -g ‘daemon of…” 2 hours ago Exited (0) About an hour ago some-nginx

### hello-world imageの起動
$ sudo docker run hello-world
LocalにDocker imageがなければDocker Hubに探しにいき、Docker imageをダウンロードする

### Docker imageのダウンロード
$ docker pull?hello-world

### Dockerコンテナの削除
$ sudo docker rm ${コンテナID}

### Docker imageの削除
$ sudo docker rmi ${ImageID}

※コンテナで使われていると、imageは削除できない
$ sudo docker rmi 667
Error response from daemon: conflict: unable to delete 6678c7c2e56c (must be forced) – image is being used by stopped container 615c9946da6d

### Nginx imageを使う
$ sudo docker pull nginx
$ sudo docker run -d –name nginx-container -p 8181:80 nginx
$ sudo docker stop nginx-container

Docker Imageをpush

### 1. Dockerにログイン
$ sudo docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don’t have a Docker ID, head over to https://hub.docker.com to create one.
Username: ${dockarId}
Password: ${password}
※ログインすると、imageをpushできるようになる

### 2. Docker Push
$ sudo docker push ${userName}/httpd
latest: digest: sha256:102635a0a51899913a5f9e0b8aeb60a2e525e016261106d928910c7***** size: 948

${userName}はDockerIdでないとrequest is deniedとなるので、注意が必要

後は、コンテナとローカルとのファイルのマウント方法ですね。

Dockerfileの操作

### Dockerfileの作成
$ vi Dockerfile

Dockerfile

FROM centos
MAINTAINER hpscript <master@hpscript.com>
# RUN: buildするときに実行
RUN echo "now building..."
# CMD: runするときに実行
CMD ["echo", "running..."]

Dockerfileの実行
$ sudo docker build -t ${UserName}/${name} .
// sudo docker build -t hpscript/echo .

$ sudo docker images
$ sudo docker run hpscript/echo
running…

### Webサーバを立ち上げて、ブラウザで中身を確認する方法
$ sudo vi Dockerfile

FROM centos
MAINTAINER hpscript <master@hpscript.com>
# RUN: buildするときに実行
# RUN echo "now building..."
# CMD: runするときに実行
# CMD ["echo", "running..."]
RUN yum install -y httpd
ADD ./index.html /var/www/html/
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

$ sudo vi index.html

<html>
hello from Docker!
</html>

$ ls
Dockerfile index.html
// build
$ sudo docker build -t hpscript/httpd .
$ sudo docker run -p 8000:80 -d hpscript/httpd
393fc9fd240e2650789466b23076165cf49b62ebdbe9f1b6****

コンテナに変更を加え、imageを作成

## 実行中のコンテナ操作
### コンテナを実行
$ sudo docker run -d ${docker id} free -s 3
59b83e48eec642ec6d2d1443a62fff6b96b7facac648eb06f4******
※「-d」でバックグラウンドで動かす
※「-s 3」で3秒おきに実行

### ログ
$ sudo docker logs ${id}
実行中のコマンドライン
$ sudo docker attach –sig-proxy=false ${id}
※「ctl」+「c」で抜ける

### 実行中のdockerを停止
$ sudo docker stop ${id}

$ sudo docker ps
$ sudo docker attach –sig-proxy=false ${id}
You cannot attach to a stopped container, start it first

### 停止中のdockerを再開
$ sudo docker start ${id}
$ sudo docker ps

## ターミナルで入ってコンテナに変更を加える
### コンテナの中に入って操作
$ sudo docker run -i -t ${ImageID} /bin/bash
※「-i」はインタラクティブモード、「-t」はターミナルを立ち上げる

実行例

vagrant@vagrant-ubuntu-trusty-64:~$ sudo docker run -i -t 470671670cac /bin/bash[root@03471f0b8a7d /]# touch hello.txt
[root@03471f0b8a7d /]# ls
bin  etc        home  lib64       media  opt   root  sbin  sys  usr
dev  hello.txt  lib   lost+found  mnt    proc  run   srv   tmp  var
[root@03471f0b8a7d /]# exit
exit

$ sudo docker ps -a

### docker imageの作成
$ sudo docker commit ${containerId} ${userName}/${name}

実際の例

$ sudo docker commit 034 hpscript/hello
sha256:da9def7208eabab27c9ffd3b05f0e5fc3c8551585396bb06ecb*********
$ sudo docker images
$ sudo docker run -i -t hpscript/hello /bin/bash
[root@f1953ff957d6 /]# ls
bin  etc        home  lib64       media  opt   root  sbin  sys  usr
dev  hello.txt  lib   lost+found  mnt    proc  run   srv   tmp  var