20200325のdockerに関する記事は10件です。

【Docker+Laravel】テスト用のダミーファイルの生成の際に出たエラーたち

状況

Dockerの環境でLaravelアプリのテストの際、ダミーの画像ファイルを作ろうと思い、公式リファレンスにもあるfile()を利用しました。

公式リファレンス(ファイルアップロードのテスト)
https://readouble.com/laravel/5.8/ja/http-tests.html?header=%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25A4%25E3%2583%25AB%25E3%2582%25A2%25E3%2583%2583%25E3%2583%2597%25E3%2583%25AD%25E3%2583%25BC%25E3%2583%2589%25E3%2581%25AE%25E3%2583%2586%25E3%2582%25B9%25E3%2583%2588

$file = UploadedFile::fake()->image('avatar.jpg');

テストしてみるとこんなエラーが...

Tests\Feature\InformationControllerTest::testStore
Call to undefined function Illuminate\Http\Testing\imagecreatetruecolor()

最初はクラスをuseしてないのかな?とかLaravelアプリ側の問題だと思いましたが、どうやらこのfile()メソッドが定義されるIlluminate\Http\UploadedFileクラスを使うには、PHP GDというPHPのライブラリが必要なようです。

PHP GDのインストール

DockerfileにPHP GDのインストールを追加してみます。

RUN apt-get update && apt-get install -y \
    zlib1g-dev \
    libzip-dev \
    mariadb-client \
  && docker-php-ext-install zip pdo_mysql gd 

上のように書き換え、再構築してみると、次はこんなエラーが

configure: error: png.h not found

調べるとdocker-php-ext-install gdをするだけでは足りず、
libfreetype6-dev
libjpeg62-turbo-dev
libpng-dev
依存関係のある三つのパッケージを事前に apt-get install する必要があるみたいです。

Dockerfileを修正します。
docker-php-ext-install gdの実行前に三つのパッケージのapt-get installを書きます。

RUN apt-get update && apt-get install -y \
    zlib1g-dev \
    libzip-dev \
    mariadb-client \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    libpng-dev \
  && docker-php-ext-install zip pdo_mysql gd 

再度buildしてみると正常に構築できました。

本当にインストールできているか確認してみます。

gd

GD Support => enabled
GD Version => bundled (2.1.0 compatible)
GIF Read Support => enabled
GIF Create Support => enabled
PNG Support => enabled
libPNG Version => 1.6.36
WBMP Support => enabled
XBM Support => enabled

ちゃんとインストールできたようですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerで構築したKibana7.6.1で自作のOSMを使用する

環境
- Debian10.3
- docker-compose 1.25.4
- Docker 19.03.7
- Elasticsearch 7.6.1
- Kibana7.6.1

Kibana7.6.1の構築
OpenStreetMapの構築

docker-composeを使用して起動するために下記のようにファイルを作成します。

docker-compose.yml
version: "3.3"

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.6.1
    environment:
      - discovery.type=single-node
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - 9200:9200
    volumes:
      - es-data:/usr/share/elasticsearch/data
  kibana:
    image: docker.elastic.co/kibana/kibana:7.6.1
    volumes:
      - ./kibana.yml:/usr/share/kibana/config/kibana.yml
    ports:
      - 5601:5601

volumes:
  es-data:
    driver: local

./kibana.ymlを編集し、OSMの設定を記述します。
Kibana7.6.1からデフォルトでは、ヴィジュアライゼーションに座標マップがなくなっているので、xpack.maps.showMapVisualizationTypesをtrueに設定します。
他にもKibanaの設定が必要な場合はこちらに記載しておきます。

kibana.yml
map.tilemap.url: "http://<OSMサーバーアドレス>/tile/{z}/{x}/{y}.png"
xpack.maps.showMapVisualizationTypes: true

コマンドを実行して起動します。

$ docker-compose up

ヴィジュアライゼーションで座標マップを開くと独自作成したOSMが反映されています。

kibana_map.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エセイー(エセSE)が挑戦する、初めてのDocker② ~Mauticをインストール

Mauticをインストール

下記サイトを参考してyamlを作成、docker-compose upしたが、MySQLへの接続ができない(Refuse)というエラーで起動しませんでした。情報が古かったようです。
http://tech.innovation.co.jp/2017/11/13/Mautic-Docker-Kohe.html
https://qiita.com/kooooooooooooooooohe/items/43f9452acc539dbd3083

Dockerhub公式サイト(https://hub.docker.com/r/mautic/mautic/)にあるYAMLファイルをコピペして実行したらうまくいった

version: '2'

services:

  mauticdb:
    image: percona/percona-server:5.7
    container_name: mauticdb
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=mysecret
    command:
      --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
    networks:
      - mautic-net

  mautic:
    image: mautic/mautic:latest
    container_name: mautic
    links:
      - mauticdb:mysql
    depends_on:
      - mauticdb
    ports:
      - 8080:80
    volumes:
      - mautic_data:/var/www/html
    environment:
      - MAUTIC_DB_HOST=mauticdb
      - MYSQL_PORT_3306_TCP=3306
      - MAUTIC_DB_USER=root
      - MAUTIC_DB_PASSWORD=mysecret
      - MAUTIC_DB_NAME=mautic
      - MAUTIC_RUN_CRON_JOBS=true
    networks:
      - mautic-net

volumes:
  mysql_data:
    driver: local
  mautic_data:
    driver: local
networks:
  mautic-net:
    driver: bridge

上記ファイルをDocker実行するフォルダに保存して、docker-compose upを実行する。

C:\Users\XXXXX\docker>docker-compose up
Creating network "docker_mautic-net" with driver "bridge"
Creating volume "docker_mysql_data" with local driver
Creating volume "docker_mautic_data" with local driver
Pulling mauticdb (percona/percona-server:5.7)...
ERROR: Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout

C:\Users\XXXXX\docker>docker-compose up
Pulling mauticdb (percona/percona-server:5.7)...
5.7: Pulling from percona/percona-server
ab5ef0e58194: Already exists
696508ef8fcc: Pull complete
821973d23839: Pull complete
64d824598147: Pull complete
627e399e55ba: Pull complete
8b576aea995a: Pull complete
73a38da52d09: Pull complete
Digest: sha256:814aa905098ecb7affc48c38f8580670115abf528f052767992a3220d8c4ab8f
Status: Downloaded newer image for percona/percona-server:5.7
Pulling mautic (mautic/mautic:latest)...
・・・・・・以下略

と、一度エラーが発生しましたが、くじけずにdocker-compose upを再実行すると、途中でエラーが出まくった(ように見えた)が、無事起動した。

ブラウザで「http://localhost:8080/」にアクセスすると下記画面が表示された。

image.png

続き1
image.png

続き2
image.png

続き3
キャプチャ忘れ・・・そのまま進めれば問題ありません。

無事にログイン画面が表示されました。
image.png

続き2でのログインIDとパスワードで、無事にダッシュボードが表示されました。
image.png

ついでに日本語化。
mauticをインストールした直後は、管理画面の表示は英語表示となっているため、管理画面の「configration」から、Default timezoneを「tokyo」に、Default languageを「japanese」とする。

image.png

画面上部の「Apply」「Save & Exit(?)」をクリックして、ログアウトすると無事に日本語化できた。

日本語に表示が変わらない場合はWebサーバー側にキャッシュが残っていることが原因なので、「/mauticインストールディレクトリ/app/cache/prod/」を削除、もしくはフォルダ名を変更することで、日本語化できるとのこと(試していないです・・・)。下記参照。
https://www.dreampockets.com/2018/08/%E3%80%90mautic%E3%80%91%E7%AE%A1%E7%90%86%E7%94%BB%E9%9D%A2%E3%81%AE%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%8C%96%E3%81%AE%E6%89%8B%E9%A0%86/

参考サイト

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker勉強メモ⑤ ネットワーク通信

はじめに

Docker勉強メモ
- Docker勉強メモ① DockerインストールからHelloWorld
- Docker勉強メモ② Dockerイメージ作ってみる
- Docker勉強メモ③ Dockerfileを作ってDockerイメージ作成からコンテナ起動までやってみる
- Docker勉強メモ④ コンテナ間通信
- Docker勉強メモ⑤ ネットワーク通信 ←ココ

やること

他のEC2インスタンスからDockerコンテナへの通信確認
以下2つの場合で通信できることを確認する

image.png

大きな緑の●から▲までのネットワーク通信できることを確認する

準備:Dockerインストール

これまで(Docker勉強メモ①~④)と違うOS Linux2 を使う。
Linux2 : amzn2-ami-hvm-2.0.20200304.0-x86_64-gp2 (ami-052652af12b58691f)

EC2インスタンスを2つ(host01, host02)作成し、Dockerをインストールする

image.png

host01
$ sudo yum update -y
$ sudo amazon-linux-extras install docker -y
$ sudo service docker start
$ ps -ef |grep docker
$ sudo usermod -a -G docker ec2-user
# -> 設定反映のため再接続

(オプション)必要なら以下もやる

host01
# Dockerサービス自動起動
$ sudo systemctl enable docker
# docker-composeインストール
$ sudo curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

通信確認(1)

この通信を確認する

image.png

確認に必要な環境はこれ

image.png

host01
# Dockerネットワーク作成
$ docker network create docnetHoge
# 作成したDockerネットワークを指定してDockerコンテナ起動
$ docker run -it -d --privileged --name containerA --network docnetHoge -p 10080:80 -d amazonlinux:latest

起動したDockerコンテナ containerA はこのようになっている。

host01
[ec2-user@ip-172-31-5-10 ~]$ docker ps -a
CONTAINER ID        IMAGE                COMMAND             CREATED             STATUS              PORTS                   NAMES
c6d137b5cbc9        amazonlinux:latest   "/bin/bash"         11 seconds ago      Up 10 seconds       0.0.0.0:10080->80/tcp   containerA

Dockerコンテナ containerA をWebサイトにするため、containerAに入る

host01
[ec2-user@ip-172-31-5-10 ~]$ docker exec -it containerA bash
bash-4.2# 

containerAの内部IPの確認と、簡易Webサーバを立てる

containerA
bash-4.2# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2      c6d137b5cbc9
bash-4.2# python -m SimpleHTTPServer 80  
Serving HTTP on 0.0.0.0 port 80 ...
172.18.0.1 - - [24/Mar/2020 07:49:41] "GET / HTTP/1.1" 200 -

ホスト host01 で、Webサイトが開くことを確認 ↓

host01
[ec2-user@ip-172-31-5-10 ~]$ curl http://localhost:10080/
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
<h2>Directory listing for /</h2>
<hr>
<ul>
<li><a href=".dockerenv">.dockerenv</a>
<li><a href="bin/">bin@</a>
<li><a href="boot/">boot/</a>
<li><a href="dev/">dev/</a>
<li><a href="etc/">etc/</a>
<li><a href="home/">home/</a>
<li><a href="lib/">lib@</a>
<li><a href="lib64/">lib64@</a>
 :
 :

ホスト host02で、Webサイトが開くことを確認 ↓

host02
[ec2-user@ip-172-31-7-186 ~]$ curl http://172.31.5.10:10080/
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
<h2>Directory listing for /</h2>
<hr>
<ul>
<li><a href=".dockerenv">.dockerenv</a>
<li><a href="bin/">bin@</a>
<li><a href="boot/">boot/</a>
<li><a href="dev/">dev/</a>
<li><a href="etc/">etc/</a>
 :
 :
# Dockerコンテナのホスト名の名前解決はできない(想定通り)
[ec2-user@ip-172-31-7-186 ~]$ curl http://containerA:10080/
curl: (6) Could not resolve host: containerA

通信できることを確認できた。

通信確認(2)

この通信を確認する

image.png

確認に必要な環境

image.png

host02 に Dockerコンテナ containerB を起動する

host02
$ docker network create docnetFuga --subnet 192.168.10.0/24
$ docker run -it -d --privileged --name containerB --network docnetFuga -p 10081:81 -d amazonlinux:latest

containerB から、containerA のWebサイトが開いた

containerB
bash-4.2# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.10.2    cc720822b8ff
bash-4.2# curl http://172.31.5.10:10080/
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
<h2>Directory listing for /</h2>
<hr>
<ul>
<li><a href=".dockerenv">.dockerenv</a>
<li><a href="bin/">bin@</a>
<li><a href="boot/">boot/</a>
<li><a href="dev/">dev/</a>
 :
 :

通信できることを確認できた。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker Desktop for MacをHomebrewでインストール(Homebrew Caskのエラー解決メモ付き)

概要

  • Docker Desktop for MacHomebrewでインストールします。
  • その際に必要となるHomebrew Caskが(自分の環境では)うまく機能しなかったので、解決方法やその他もろもろを含めて、今回ちょっとした覚えがき的に記すこととします!

先に結論

Docker Desktop for Macのインストール

Terminalで以下コマンドを実行します。

$ brew install docker

$ brew cask install docker

$ open /Applications/Docker.app

$ brew cask install dockerがうまくいかない場合

Terminalで以下コマンドを実行します。

$ brew update-reset && brew update

実行環境

バージョン
macOS Mojave 10.14.6
Homebrew 2.2.10
Docker 19.03.8

Homebrew Caskとは

  • Homebrewの拡張。
  • Macのデスクトップアプリをbrewbrew cask)コマンドでインストールできるようになる。
  • Terminalコマンド入力による「CLIベースのインストール」実行ができるので、アイコンをアプリケーションに移して。。。とかしなくてもよくなる。

"インストールするのに、このアイコンをドラッグして..."なんてことは、もう不要です!
Homebrew Caskは、Homebrewを拡張し、AtomやGoogle ChromeなどのGUI macOSアプリケーションのインストールと管理に、エレガントさ、シンプルさ、スピードをもたらします。
バイナリ形式で配布されるmacOSアプリケーションの管理に対して、フレンドリーなCLIワークフローを提供することで実現します。

出典:Homebrew Cask (GitHub)

手順 (およびbrew cask installエラー → 解決の流れ)

Homebrewでのインストールを、いつもと同じようにTerminalで実行します。

$ brew install docker

ただし、これだけではDocker.appが入らないので、つづけてbrew cask install dockerを実行する必要があります。

。。。が、自機Macでbrew caskがどうも機能しないことが判明。

$ brew cask

==> Tapping homebrew/cask
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask'...
.
.
.
Error: Failure while executing; `git clone https://github.com/Homebrew/homebrew-cask /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask` exited with 128.
Follow the instructions here:
.
.
.

Terminalからbrew update-reset && brew updateを実行して、Homebrewとformula(brewで入れたパッケージ)をアップデートしなおします。
(参考:Homebrew Cask (GitHub)

$ brew update-reset && brew update

==> Fetching /usr/local/Homebrew...
.
.
.
From https://github.com/Homebrew/brew
   5518f276e..87fcba5d0  master     -> origin/master

==> Resetting /usr/local/Homebrew...
Branch 'master' set up to track remote branch 'master' from 'origin'.
Switched to and reset branch 'master'
Your branch is up to date with 'origin/master'.

==> Fetching /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core...

==> Resetting /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core...
Branch 'master' set up to track remote branch 'master' from 'origin'.
Reset branch 'master'
Your branch is up to date with 'origin/master'.

Already up-to-date.

つつがなくアップデートできたようなので、あらためてbrew caskを実行します。

$ brew cask

==> Tapping homebrew/cask
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask'...
.
.
.

Tapped 1 command and 3502 casks (3,618 files, 204.8MB).
Homebrew Cask provides a friendly CLI workflow for the administration
of macOS applications distributed as binaries.
.
.
.
See also "man brew-cask"

どうやら、うまくcloneして持ってこれたみたいです!

Dockerをbrew caskで、あらためてインストール

というわけで
brew caskの実行環境準備が整ったので、Docker.appインストールに再アタックしてみます。

$ brew cask install docker

Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/cask).
==> Updated Casks
onyx

==> Downloading https://download.docker.com/mac/stable/43472/Docker.dmg
######################################################################## 100.0%
==> Verifying SHA-256 checksum for Cask 'docker'.
==> Installing Cask docker
==> Moving App 'Docker.app' to '/Applications/Docker.app'.
🍺  docker was successfully installed!

うまくインストールできました。

$ open /Applications/Docker.app

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

ちゃんとDockerデーモン起動してます^^!
(コンテナ自体はまだない)


参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

githubでtagつけたら、自動でDoker buildしてAWS ECRにpushするgithub action

初版20200325

php+nginxアプリケーションの場合なので2つのコンテナをpushしている。

name: Build and Push Image to ECR

# 条件
on:
  push:
    tags: 
      - v* # tagが"v"からはじまってる場合に絞ってる。

# 処理
jobs:
  build:
    name: Build and Push
    runs-on: ubuntu-latest
    steps:
      # tag名を変数化
      - name: Get the version (tag)
        id: get_version
        run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
      # 指定タグでチェックアウト
      - uses: actions/checkout@v1
        with:
          ref: refs/tags/${{ steps.get_version.outputs.VERSION }}
          token: ${{ secrets.GitHub_PAT }}
      # AWS credentials設定
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1
      # ECRログイン
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
      # ビルド, push処理
      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPO_APP: ${{ secrets.AWS_ECR_REPO_APP }}
          ECR_REPO_NGINX: ${{ secrets.AWS_ECR_REPO_NGINX }}
          XGITHUB_USER: ${{ secrets.XGITHUB_USER }}
          XGITHUB_PASS: ${{ secrets.XGITHUB_PASS }}
          XGITHUB_TAG: ${{ steps.get_version.outputs.VERSION }}
        run: |
          # 必要に応じディレクトリ移動してビルド
          cd docker
          docker-compose build

          # Tagging app & push
          docker tag $ECR_REPO_APP:latest $ECR_REPO_APP:$XGITHUB_TAG
          docker tag $ECR_REPO_APP:$XGITHUB_TAG $ECR_REGISTRY/$ECR_REPO_APP:$XGITHUB_TAG
          docker tag $ECR_REPO_APP:latest $ECR_REGISTRY/$ECR_REPO_APP:latest
          echo "Tagged ... ${ECR_REGISTRY}/${ECR_REPO_APP}:${XGITHUB_TAG}"
          docker push $ECR_REGISTRY/$ECR_REPO_APP:$XGITHUB_TAG
          docker push $ECR_REGISTRY/$ECR_REPO_APP:latest
          echo "Pushed ... ${ECR_REGISTRY}/${ECR_REPO_APP}:${XGITHUB_TAG}"

          # Tagging nginx & push(上記と同じ処理をrepositry変えて繰り返してるだけ)
          docker tag $ECR_REPO_NGINX:latest $ECR_REPO_NGINX:$XGITHUB_TAG
          docker tag $ECR_REPO_NGINX:$XGITHUB_TAG $ECR_REGISTRY/$ECR_REPO_NGINX:$XGITHUB_TAG
          docker tag $ECR_REPO_NGINX:latest $ECR_REGISTRY/$ECR_REPO_NGINX:latest
          echo "Tagged ... ${ECR_REGISTRY}/${ECR_REPO_NGINX}:${XGITHUB_TAG}"
          docker push $ECR_REGISTRY/$ECR_REPO_NGINX:$XGITHUB_TAG
          docker push $ECR_REGISTRY/$ECR_REPO_NGINX:latest
          echo "Pushed ... ${ECR_REGISTRY}/${ECR_REPO_NGINX}:${XGITHUB_TAG}"
      # Slack通知とか必要に応じて
#     - name: Notify push finish to Slack
#       run: curl -X POST -H 'Content-type:application/json' --data '{"text":"'"${GITHUB_REPOSITORY}"'\n【FINISH】Pushed Image to ECR!!"}' ${{ secrets.SLACK_WEBHOOK }}
  • secrets はgithub repositryのSettings > Secretsから便宜設定
    • AWS_ACCESS_KEY_ID
    • AWS_ECR_REPO_APP
    • AWS_ECR_REPO_NGINX
    • AWS_SECRET_ACCESS_KEY
    • XGITHUB_PASS
    • XGITHUB_USER
  • 面倒なのでとりあえずgithub user/passを指定しちゃってるが実際は鍵認証などでやるべき(secrets.GitHub_PATでできそうな感じする)
  • 他ビルドに必要なenvがあればsecretsに設定する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

githubでtagつけたら、自動でDocker buildしてAWS ECRにpushするgithub actions

初版20200325

php+nginxアプリケーションの場合なので2つのコンテナをpushしている。

name: Build and Push Image to ECR

# 条件
on:
  push:
    tags: 
      - v* # tagが"v"からはじまってる場合に絞ってる。

# 処理
jobs:
  build:
    name: Build and Push
    runs-on: ubuntu-latest
    steps:
      # tag名を変数化
      - name: Get the version (tag)
        id: get_version
        run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
      # 指定タグでチェックアウト
      - uses: actions/checkout@v1
        with:
          ref: refs/tags/${{ steps.get_version.outputs.VERSION }}
          token: ${{ secrets.GitHub_PAT }}
      # AWS credentials設定
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1
      # ECRログイン
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
      # ビルド, push処理
      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPO_APP: ${{ secrets.AWS_ECR_REPO_APP }}
          ECR_REPO_NGINX: ${{ secrets.AWS_ECR_REPO_NGINX }}
          XGITHUB_USER: ${{ secrets.XGITHUB_USER }}
          XGITHUB_PASS: ${{ secrets.XGITHUB_PASS }}
          XGITHUB_TAG: ${{ steps.get_version.outputs.VERSION }}
        run: |
          # 必要に応じディレクトリ移動してビルド
          cd docker
          docker-compose build

          # Tagging app & push
          docker tag $ECR_REPO_APP:latest $ECR_REPO_APP:$XGITHUB_TAG
          docker tag $ECR_REPO_APP:$XGITHUB_TAG $ECR_REGISTRY/$ECR_REPO_APP:$XGITHUB_TAG
          docker tag $ECR_REPO_APP:latest $ECR_REGISTRY/$ECR_REPO_APP:latest
          echo "Tagged ... ${ECR_REGISTRY}/${ECR_REPO_APP}:${XGITHUB_TAG}"
          docker push $ECR_REGISTRY/$ECR_REPO_APP:$XGITHUB_TAG
          docker push $ECR_REGISTRY/$ECR_REPO_APP:latest
          echo "Pushed ... ${ECR_REGISTRY}/${ECR_REPO_APP}:${XGITHUB_TAG}"

          # Tagging nginx & push(上記と同じ処理をrepositry変えて繰り返してるだけ)
          docker tag $ECR_REPO_NGINX:latest $ECR_REPO_NGINX:$XGITHUB_TAG
          docker tag $ECR_REPO_NGINX:$XGITHUB_TAG $ECR_REGISTRY/$ECR_REPO_NGINX:$XGITHUB_TAG
          docker tag $ECR_REPO_NGINX:latest $ECR_REGISTRY/$ECR_REPO_NGINX:latest
          echo "Tagged ... ${ECR_REGISTRY}/${ECR_REPO_NGINX}:${XGITHUB_TAG}"
          docker push $ECR_REGISTRY/$ECR_REPO_NGINX:$XGITHUB_TAG
          docker push $ECR_REGISTRY/$ECR_REPO_NGINX:latest
          echo "Pushed ... ${ECR_REGISTRY}/${ECR_REPO_NGINX}:${XGITHUB_TAG}"
      # Slack通知とか必要に応じて
#     - name: Notify push finish to Slack
#       run: curl -X POST -H 'Content-type:application/json' --data '{"text":"'"${GITHUB_REPOSITORY}"'\n【FINISH】Pushed Image to ECR!!"}' ${{ secrets.SLACK_WEBHOOK }}
  • secrets はgithub repositryのSettings > Secretsから便宜設定
    • AWS_ACCESS_KEY_ID
    • AWS_ECR_REPO_APP
    • AWS_ECR_REPO_NGINX
    • AWS_SECRET_ACCESS_KEY
    • XGITHUB_PASS
    • XGITHUB_USER
  • 面倒なのでとりあえずgithub user/passを指定しちゃってるが実際は鍵認証などでやるべき(secrets.GitHub_PATでできそうな感じする)
  • 他ビルドに必要なenvがあればsecretsに設定する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker初心者がCakePHP3の開発環境構築時イメージ作成を考える

はじめに

CakePHPを体系的に学習するついでに、Dockerで開発環境を構築して、どのようコンテナを作るのがいいのかをまとめようと思います。
個人的にこれがいいと思う開発環境構築方法が書ければ良いかなと思います。
ベースイメージを決めてそれに加えて、必要なものをインストールする形になると思います。
また、コンテナを複数使用する場合が考えられるため、その際にはdocker composeをしようします。

開発環境の内容

今回は以下の条件でシンプルなWEBアプリ開発環境を作成しようと思います。

  • PHP7.2.5
  • CakePHP3
  • Apache
  • MySQL

コンテナの種類

  • CakePHP3&APache(fpmではなくモジュール版PHPを使用する)
  • MySQL

CakePHP3用イメージ

使用するイメージの選ぶ基準

PHPの公式イメージは多くのイメージが存在する。PHPのバージョンや、同梱されているwebサーバなど、様々な種類のイメージがあります。
今回の開発環境を作るとしてもかなりの数があり絞れない。
イメージの選び方として、参考になるQiita記事がありました。
Dockerベースイメージの特徴と比較・選び方

軽く書くと以下の内容が記載されていた。

  • イメージが誰がどのように作成したのか
  • セキュリティ的に大丈夫か
  • イメージのサイズ
  • アプリの実行環境を整えるまでに必要な手数

確かに納得できる内容でした。普段「アプリの実行環境を整えるまでに必要な手数」だけ気にしていたと思います。
上記内容を参考にすると以下に絞れる。
1. PHPまたはOSの公式イメージ
2. 軽量なイメージ

今回はシンプルなWEBアプリであり元々手数はかからないため「アプリの実行環境を整えるまでに必要な手数」の観点はあまり気にしなくて良さそう。

軽量なイメージAlpine Linux

軽量なイメージを選ぶことのメリットとしては、以下になりま//す。

  • デプロイが早くなる
  • 起動が早くなる

アプリケーションなどの性能には基本的に軽量化とは関係ありません。
他のイメージよりも圧倒的なイメージがAlpine Linuxです。
圧倒的に軽いことがわかるQiitaの記事がありました。
Alpine Linux で Docker イメージを劇的に小さくする

そのためAlpine Linuxを選択する方が良いでしょう。

Alpineイメージを使う

Alpine Linuxがベースになったイメージは多くありましたが、
自分で使いこなせそうなのが、Alpineだけのイメージでした。PHP公式のイメージやApache公式のイメージを試しましが、
使いこなせず、どちらも自分にはわかりずらかった。
そのため結局、PHPなど何もインストールされていないAlpineイメージ
を選択しました。
ここにPHPやAPacheをインストールしていきます。

プロジェクトのディレクトリ構造

cake3app
├── docker
│   ├── Dockerfile
│   └── app // php.iniとhttpd.confが格納されている
├── docker-compose.yml
└── sample // CakePHPのソース
    ├── README.md
    ├── bin
    ├── composer.json
    ├── composer.lock
    ├── config
    ├── index.php
    ├── logs
    ├── phpunit.xml.dist
    ├── plugins
    ├── src
    ├── tests
    ├── tmp
    ├── vendor
    └── webroot

DockerFile

PHPと必要なCakeに必要なライブラリとComposerをインストールして、
Cakeのソースをコピーして、composer installコマンド実行する処理になります。

DockerFile
FROM alpine:3.10

## Packageインストール intlはCakePHPで必須のライブラリらしいエラーが表示される。php.iniでも有効にしておく必要がある
RUN apk add --update --no-cache php7 php7-pdo_mysql php7-openssl php7-curl php7-json php7-mbstring \
    php7-apache2 php7-pdo_odbc php7-pdo_mysql php7-gd php7-pecl-apcu php7-mysqli php7-fpm php7-intl php7-phar php7-dom php7-xml php7-simplexml php7-tokenizer php7-xmlwriter php7-session apache2

## composerをインストール
COPY --from=composer /usr/bin/composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /usr/bin/composer
ENV PATH $PATH:/composer/vendor/bin

COPY ./sample /var/www/html/sample/
WORKDIR /var/www/html/sample/
RUN composer install --no-interaction
CMD ["httpd", "-D", "FOREGROUND"]

docker compose

docker-compose.yml
version: "3"
services:
  php:
    build:
     context: .
     dockerfile: ./docker/Dockerfile
    volumes:
      - ./sample:/var/www/html/sample
      - ./docker/app/php.ini:/usr/local/lib/php.ini
      - ./docker/app/httpd.conf:/etc/apache2/httpd.conf
    tty: true
    ports:
     - 80:80
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: cake_php
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --explicit_defaults_for_timestamp=1
    ports:
      - 3306:3306

コンテナ

  • php
    • Apache Webサーバ
    • CakePHP
  • mysql

これでローカル環境でWebサーバとアプリケーションとDBの一式の開発環境が構築できます。

まとめ

たくさんのイメージが存在するが、結局Alpineのみのイメージをベースにしえ必要なものをインストールする方が、使いやすく、余計なものもないため軽量を維持できるというメリットがあるなと思いました。
あと世の中的にnginxをしようしている人が多い印象ですが、レンタルサーバなどの複数のプロジェクトを同一サーバにデプロイしない限りApacheの方がメリットが大きいらしいです。
1コンテナ1プロセスで運用するのがベターということですが、ApacheでPHPを実行する場合は、同一プロセスでPHPが動くので、それも守っている。
結局PHPはApacheが一番相性いいのではと思いました。
Apacheの設定ファイルの構造はちゃんと理解していないので、どこかで勉強しないとですね。
意外とAlpineで構築したという記事が少なく、CentOSかUbuntuを使っている人が多かったのが気になりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerを使ってAlpineでMatplotlibを日本語化する

こちらのDockerfileを作成しました。

はじめに

大学で自然言語処理の研究室に配属されることになったので言語処理100本ノックを進めています。その問題でmatplotlibを日本語化しなければならない問題があったので、最近勉強しているDockerを使って環境を構築してみました。

環境

  • Docker 19.03.8

Dockerfileについて

Dockerで環境構築するにあたって、

  • ベースイメージをAlpineにする
  • Anacondaを使用しない
  • numpyもインストールする

ことを目標にしました。

pipでmatplotlibとnumpyをインストールする際に、ライブラリが足りずにエラーが出てしまったので、alpineのパッケージマネージャであるapkでbuild-baseとfreetype-devを追加しました。このうち、build-base内のlibstdc++とfreetype-devは実行時に利用されるため、削除しないようにしました。

また日本語に対応しているフォントとしてNotoSansCJKjpを入れました。そしてmatplotlibの設定ファイルでこのフォントを使用するようにし、キャッシュを削除しました。

最後に

Dockerはとても便利なのでこれからも使っていきたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker で AWS Lambda の Python 用 Layer を作成する

AWS Lambda の Python ランタイムでよく使うモジュールを Lambda Layers に登録しようと思ったが、EC2 インスタンスを立ち上げてパッケージを作るのが面倒なので Docker でできるようにした。

Lambda Layers とは何か

  • ファイルを zip で固めたものをアップロードして「レイヤー」として登録することができる
  • Lambda Function にレイヤーを追加すると、ランタイムの /opt 以下に固めたファイルが展開されて実行時に利用できるになる
  • 言語ごとに指定された名前のディレクトリの中にモジュールを入れておくと、Lambda Function から読み込めるようにパスを通してくれる
    • 例えば Python ランタイムの場合、レイヤー zip 内の python という名前のディレクトリに Python モジュールを入れておくと Lambda Function 側でそのモジュールを import で読み込むことができる

詳しくは: AWS Lambda レイヤー - AWS Lambda

Layer を作成するための Docker イメージを作る

Python 3.8 ランタイムは Amazon Linux 2 で動いているらしい 1 ので、本来であれば Amazon Linux 2 の EC2 インスタンスを立ててその中でレイヤーを作るべきである (別に Linux ならなんでもいいかもしれないが、少なくとも macOS で作ったレイヤーは AWS Lambda では動かない 2 ) のだが、実は Amazon Linux は Docker Hub で公式イメージが配布されている 3 ので、これをベースにして Python 3.8 をインストールした Docker イメージを作ればわざわざ EC2 インスタンスを立てる必要がない。

Dockerfile
FROM amazonlinux:2

ARG PYTHON_VERSION=3.8.2

RUN yum update -y && yum install -y tar gzip make gcc openssl-devel bzip2-devel libffi-devel \
  && curl https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz | tar xz \
  && cd Python-${PYTHON_VERSION} && ./configure && make && make install \
  && cd - && rm -rf Python-${PYTHON_VERSION}

ADD entrypoint.sh /

RUN yum install -y zip \
  && mkdir /python \
  && chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

Entrypoint には pip install して zip で固めるスクリプトを登録しておく。

entrypoint.sh
#!/bin/bash -eu

SRC=/python
DIST=/dist/layer.zip

pip3 install -t ${SRC} $@
rm -f ${DIST}
zip -q -r ${DIST} ${SRC}

イメージをビルドする。

$ docker build . -t bundle-pip-modules-for-aws-lambda-layers:python3.8

イメージ名が長ったらしいが別にここは何でもいい。

Docker イメージを使って Layer を作成する

例えば Pandas が使える Lambda Layer を作成する場合。

$ docker run --rm \
    -v $(pwd):/dist \
    bundle-pip-modules-for-aws-lambda-layers:python3.8 \
        pandas

成功すればカレントディレクトリに layer.zip が作成される。

上の例では直接 pandas を指定したが、イメージ名以降の引数は pip3 install で指定できる引数を全て渡せるので、例えば requirements.txt をマウントした上で -r オプションを指定することで多くのモジュールをまとめて Layer にすることもできる。

$ echo 'pandas' > requirements.txt
$ docker run --rm \
    -v $(pwd)/requirements.txt:/requirements.txt \
    -v $(pwd):/dist \
    bundle-pip-modules-for-aws-lambda-layers:python3.8 \
        -r requirements.txt

Layer を登録する

作成された layer.zip をアップロードする。

image.png

Layer を使用する

一番簡単な例として、Pandas の読み込み以外は何もしない Lambda Function を作ってみる。

lambda_function.py
import pandas

def lambda_handler(event, context):
    pass

作った Lambda Function に登録した Layer を追加する。

image.png

この Lambda Function を実行してみてエラーが出なければ OK 。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む