20190909のdockerに関する記事は12件です。

docker-composeで「docker-compose up」ができないとき

docker-composeでdocker-compose upを実行すると、以下のように

(略)

web_1        | 
web_1        | - Gracefully stopping, waiting for requests to finish
web_1        | === puma shutdown: 2019-09-09 13:48:21 +0000 ===
web_1        | - Goodbye!
web_1        | Exiting
app_web_1 exited with code 1

といったエラーが出てしまうときがあります。

解決方法

docker-composeでは、gemを新規で導入するときには、まず以下のコマンドを実行すれば良いだけでした。

$ docker-compose build

それから、docker-compose upを実行すれば、通常通りコンテナが生成されるようになります。

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

OpenGrok+Dockerで、ダウンタイムがほぼ無いソース検索を作る

まえおき

OpenGrok+Dockerで、使い捨てソース検索エンジンをつくる
https://qiita.com/YusukeIwaki/items/3f855202e9c00247d5c7

OpenGrokの公式Dockerイメージでソース検索サーバーを立てる
https://qiita.com/YusukeIwaki/items/ccf7dab6b1a284bbff26

と、Docker+OpenGrokでのソース検索サーバを建てるネタは放出してきたんだけども、
実のところ今までのソース検索は「30分に1度、インデックス再構築のために、4分くらいダウンタイムが発生する」という、大きな欠点があったことは伝えていなかった。

自分用のソース検索だったらそれでよかったんだけど、周りに使ってもらい始めると、30分に1回「なんかおかしいんですけど」って言われるリスクと戦わないといけないので、いい加減対処しようってなった。
ということで、今回はその欠点を解決した版を紹介しようと思う。

なぜダウンタイムが発生するのか

雑に絵で説明しよう。理由は2つある。

いままでの構成はこう。ソースコードはホスト側にあって、それをbindfsでDocker側にマウントする&Docker側でインデックスが保持される。

これだと、ソースコードを最新化するタイミングでまずインデックスと実ソースが微妙に不整合な状態になる。「検索結果には出てくるのに、実際に見に行くと最新ソースでは消されていたのでなくなっていた」みたいなことが起きる。

そんで、次に最大の問題であるダウンタイムが発生する。まだ出来上がってないインデックスを外からHTTPでアクセスしに来ちゃうからだ。

Dockerらしく、裏でインデックス作って、できあがったら差し替えればいいじゃない?

ソースコードも全部コンテナに押し込めてしまえば、
こんな感じで、裏でdocker buildしておいて、インデックス生成までdocker buildでやってしまって
イメージのビルドが終わったら、あとは好きなタイミングで、古いコンテナをstopして新しいコンテナをrunすれば、せいぜい2〜3秒程度のダウンタイムで済むんじゃないか?という発想。

公式Dockerイメージでは無理である

Oracle公式のopengrokのイメージは、docker runしたタイミングで初めてインデックス生成が行われる。
先に書いたように、HTTPを受け付けるにもかかわらずインデックスが出来上がってない状態、みたいなのが少なからずできてしまうので、これをそのまま使うことはできない。

仕方がないので、自前で用意することにした。
https://github.com/YusukeIwaki/docker-opengrok-alpine

https://github.com/oracle/opengrok/wiki/How-to-setup-OpenGrok の手順を参考にしつつ、
公式OpenGrokイメージの https://github.com/oracle/opengrok/blob/master/Dockerfilehttps://github.com/oracle/opengrok/tree/master/docker を斜め読みして作成した。
Alpine Linuxの apk add --no-cache ctags だとuniversal-ctagsじゃなくて古いほうのctagsが入るので、universal-ctagsを自前でビルドしないといけないのが微妙に厄介。
他は割とすんなり理解できるだろう。

裏でイメージをビルドする君をつくる

イメージのビルドスクリプトは、

  • 最新のdevelopブランチでも変更がないなら、全部キャッシュを効かせたい
  • 最新のdevelopブランチが変更されているなら、git cloneの直前まではキャッシュを効かせ、それ以降はビルドしたい

のようにする。

Dockerfileでgit clone を使う際にキャッシュをADDで回避
https://qiita.com/sawanoboly/items/ac559c43b9662304931a

で書かれているように、ADDでorigin/developのコミットハッシュを書いたファイルをコンテナに送り込むといい。
GitHub APIを使うでもいいし、

git ls-remote git@bitbucket.org:YusukeIwaki/some_repository.git refs/heads/develop | cut -f1 > origin_develop.sha1.txt

みたいな感じで愚直にファイルを作るでもいいと思う。

ビルド自体は、シンプルに docker build -t some-source-search . するだけ。

コンテナを差し替える君をつくる

雑だが、

docker ps | grep "0.0.0.0:8080" | cut -f1 -d' ' | xargs --no-run-if-empty docker stop | xargs --no-run-if-empty docker rm
docker run -d -p 8080:8080 some-source-search

こんな感じでいける。

Rundeckでジョブ管理すると楽

  • docker buildが終わり次第、コンテナの差し替えを行う
  • 日中のインデックス更新は30分に1回おこなう
  • ログは3日間分くらいは残しておきたい

などなど、cronで管理するのはいやなので、Rundeckにまかせてしまう。
https://www.rundeck.com/open-source

セットアップ方法は、ぐぐればでてくるので省略。

まとめ

切り替えは雑ですが、イミュータブルデプロイみたいなかんじの構成にすることで、かなり快適にソース検索ができるようになります。

公式OpenGrokイメージが似たようなDockerfileを提供してくれたら、もっとみんな幸せになるんじゃないかなぁ...。

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

Dockerコンテナ上でイメージファイルをマウントする

3行まとめ

  1. partedコマンドでバイト単位のパーティション開始位置を確認する。
  2. docker container runコマンドに--privilegedオプションを付加する。
  3. mount --options loop,offset=[オフセット値] [イメージファイル] [マウント先]でマウントする。

1. 概要

 Dockerコンテナ内でイメージファイル(例えばOSイメージ)をマウントしたいことがあります。
毎回似たようなことを調べているので、整理も兼ねて具体例をここに記しておきます。

2019年9月11日12時55分追記: mt08さんからのコメントによると、Raspbianは公式のルートファイルシステムが別途配布されているとのことです。そのため、Raspbianを対象にこれらを行うことにはほとんど意味がありませんが、他のイメージファイルでは有用かと思います。

2. 環境

 今回試した環境は以下の通りです。

  • OS: Ubuntu 16.04.5 LTS
  • Docker: 18.09.4
host$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.5 LTS"

host$ docker version
Client:
 Version:           18.09.4
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        d14af54
 Built:             Wed Mar 27 18:34:51 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.4
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.8
  Git commit:       d14af54
  Built:            Wed Mar 27 18:01:48 2019
  OS/Arch:          linux/amd64
  Experimental:     false

3. 対象イメージ

 今回の対象イメージは、Raspberry Pi用のLinuxディストリビューションである「Raspbian Buster Lite」(2019-07-10版)です。
Dockerコンテナ内でダウンロードしても良いですが、試行錯誤を容易にするため、Dockerコンテナの外側でダウンロードしました。

host$ wget https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-07-12/2019-07-10-raspbian-buster-lite.zip
host$ ls -l 2019-07-10-raspbian-buster-lite.zip
-rw-rw-r-- 1 yuya yuya 426250971 Jul 10 09:23 2019-07-10-raspbian-buster-lite.zip

host$ sha256sum 2019-07-10-raspbian-buster-lite.zip
9e5cf24ce483bb96e7736ea75ca422e3560e7b455eee63dd28f66fa1825db70e  2019-07-10-raspbian-buster-lite.zip

host$ unzip 2019-07-10-raspbian-buster-lite.zip
host$ sha256sum 2019-07-10-raspbian-buster-lite.img
cce3cdaa078597d0b2181f7e121a452346c72bca9095893e56e01c82e524c276  2019-07-10-raspbian-buster-lite.img

4. Dockerコンテナ内でのマウント

 今回はUbuntu 18.04のDockerコンテナ上で作業を行いました。
以下、Dockerホスト側のプロンプトをhost$、Dockerコンテナ内のプロンプトをdocker$で示します。

host$ docker image pull ubuntu:18.04
18.04: Pulling from library/ubuntu
Digest: sha256:d1d454df0f579c6be4d8161d227462d69e163a8ff9d20a847533989cf0c94d90
Status: Image is up to date for ubuntu:18.04

host$ docker container run --interactive --tty --rm --privileged \
  --volume $(pwd):/workspace \
  ubuntu:18.04

 まず、イメージファイルに含まれるパーティションと、その位置(オフセット)を確認します。
今回のイメージには2つのパーティション(FAT32とext4)が含まれており、2つ目のパーティションが目的のパーティションです。このパーティションのStartの値(今回は276824064)を控えておきます。

 partedではなくfdiskでも確認できますが、セクタ単位で表示されるためバイト単位に換算が必要です。partedであればバイト単位で表示できます。

docker$ apt-get update && apt-get install --yes --no-install-recommends parted
docker$ parted /workspace/2019-07-10-raspbian-buster-lite.img unit B print
Model:  (file)
Disk /workspace/2019-07-10-raspbian-buster-lite.img: 2197815296B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start       End          Size         Type     File system  Flags
 1      4194304B    272630271B   268435968B   primary  fat32        lba
 2      276824064B  2197815295B  1920991232B  primary  ext4

 続いて、イメージファイルをマウントします。mountコマンドのoffset=に、先ほど控えた値(パーティションの開始位置)を指定します。
マウントが成功すると、イメージファイルの内容を確認することができます。

docker$ mkdir --parents /mnt/image
docker$ mount --options loop,offset=276824064 /workspace/2019-07-10-raspbian-buster-lite.img /mnt/image

docker$ lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0    7:0    0    80K  0 loop
loop1    7:1    0    80K  0 loop
loop2    7:2    0   1.8G  0 loop /mnt/image
sda      8:0    0   3.7T  0 disk
`-sda1   8:1    0   3.7T  0 part /workspace
sdb      8:16   0 232.9G  0 disk
|-sdb1   8:17   0   512M  0 part
|-sdb2   8:18   0 216.5G  0 part
`-sdb3   8:19   0  15.9G  0 part
sdc      8:32   0   2.7T  0 disk
sdd      8:48   0 489.1G  0 disk
`-sdd1   8:49   0   489G  0 part /etc/hosts
sr0     11:0    1  1024M  0 rom

docker$ ls -l /mnt/image/
total 88
drwxr-xr-x  2 root root  4096 Jul 10 00:08 bin
drwxr-xr-x  2 root root  4096 Jul 10 00:20 boot
drwxr-xr-x  4 root root  4096 Jul 10 00:03 dev
drwxr-xr-x 80 root root  4096 Jul 10 00:21 etc
drwxr-xr-x  3 root root  4096 Jul 10 00:07 home
drwxr-xr-x 16 root root  4096 Jul 10 00:09 lib
drwx------  2 root root 16384 Jul 10 00:20 lost+found
drwxr-xr-x  2 root root  4096 Jul 10 00:03 media
drwxr-xr-x  2 root root  4096 Jul 10 00:03 mnt
drwxr-xr-x  3 root root  4096 Jul 10 00:07 opt
drwxr-xr-x  2 root root  4096 Jun  6 15:42 proc
drwx------  2 root root  4096 Jul 10 00:03 root
drwxr-xr-x  4 root root  4096 Jul 10 00:03 run
drwxr-xr-x  2 root root  4096 Jul 10 00:09 sbin
drwxr-xr-x  2 root root  4096 Jul 10 00:03 srv
drwxr-xr-x  2 root root  4096 Jun  6 15:42 sys
drwxrwxrwt  2 root root  4096 Jul 10 00:21 tmp
drwxr-xr-x 10 root root  4096 Jul 10 00:03 usr
drwxr-xr-x 11 root root  4096 Jul 10 00:03 var

5. 補足: --privilegedオプションについて

 docker container runコマンドに--privilegedオプションを付けない場合、以下の通りmountコマンドがエラーとなります。

host$ docker container run --interactive --tty --rm \
  --volume $(pwd):/workspace \
  ubuntu:18.04

docker$ mount -o loop,offset=276824064 /workspace/2019-07-10-raspbian-buster-lite.img /mnt/image
mount: /mnt/image: mount failed: Operation not permitted.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

サーバサイドKotlin用Docker, docker-compose

サーバサイドと書いてありますが、Android関係ないってことを表したかっただけです。
内容は最低限のものになってます。

ローカルでApache Beam SDK動かす用に雑に作ったものです。

とりあえずミニマムのexampleが一つ動いたので載せておきます。

Dockerfile

FROM gradle:5.4-jdk-alpine

ENV APP_ROOT /usr/src/app

WORKDIR $APP_ROOT

USER root

RUN apk add --no-cache curl \
    zip \
    libc6-compat \
    bash

RUN ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2

RUN curl -s https://get.sdkman.io | bash

RUN bash -c " \
    source "$HOME/.sdkman/bin/sdkman-init.sh" && \
    sdk install kotlin 1.3.50 \
"

docker-compose.yml

docker-compose.yml
version: '2'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/usr/src/app:cached

動かす時

$ docker-compose run --rm app bash
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerとVirtualBoxでLAMP環境をサクッと構築する

はじめに

Dockerに興味あるけど結局何ができるの?…という初心者向けに、備忘録も兼ねて投稿します。
30分でLAMP環境を構築することを目標に進めていきます。
Windows向けですが、基本的にMacでも同じようにできると思います。

え、XAMPPとかMAMPはダメなの…?

↑みたいなことを自分でも思っていましたが、結局デプロイするときDocker使っていた方が楽なのに気づきました。
開発環境からDockerでやっていればサクッと本番環境を構築できるのがありがたいです。
Docker Composeを使えば、起動設定まで自動化できるのでありがたい。
なので共有します。
※本記事ではやりませんが、SSL化もコンテナを使えば簡単に済みます。
というわけで、いずれプロダクトを公開するんだという予定のある方におすすめします。

環境

使用OS Win10 64bit

使用するもの

1.Docker Toolbox
これをインストールするだけで
Docker-machine
Docker
VirtualBox
ターミナル
これらが手に入り、サクッと導入できるので今回はこれでいきます。

2.Docker-machine
これはDockerがインストールされたDockerホスト(本記事ではVirtualBoxが提供する仮想マシーン)を作成してくれます。

3.VirtualBox
これは仮想環境を提供してくれるもの。Dockerホストの実体はここにあります。ですがDockerホストは基本的にdocker-machineコマンドによって接続するので今回では共有フォルダの設定くらいでしか触りません。

4.Docker Quickstart Terminal
いわゆるターミナルです。ここからDocker-machineやDockerなどのコマンド操作していきます。

5.テストアプリ
環境だけ構築しても寂しいので、LAMPで動かすテストアプリを用意しておきました。
これはGitHubからクローンしてご利用ください。

前提知識

ホストマシーン
今回の場合はWinマシーンです。ここからdocker-machineコマンドを使用して、DockerホストへとSSH接続します。

Dockerホスト
今回はVirtualBoxが提供する仮想マシーンです。Docker-machineによって、ここにDockerがインストールされてDockerコマンドはここで使用していくことになります。
今回はテスト環境なのでVirtualBox内の仮想マシーンですが、本番環境時ではあなたが用意したサーバになったりするでしょう。

Dockerイメージ
ざっくり言うとコンテナの元になるもの。
基本的なものはDocker Hubがだいたい用意してくれている。
カスタマイズしたい場合はDockerfileでビルド。

Dockerコンテナ
Dockerイメージから起動する軽量な仮想マシーン。
Docker Hubから公式イメージをダウンロードしてきて、Dockerfileで好みのイメージをビルド→目当ての機能をDockerコンテナで実現を自分はよくやります。

Dockerfile
Dockerイメージを自分好みに改造するもの。

Docker Compose
サービスの稼働には、Dockerイメージのビルドに加え、コンテナの起動設定もしなくてはなりません。
イメージのビルドはDockerfileがしてくれるのに対して、コンテナの起動設定はこれが担ってくれます。手動でターミナルからコマンドを打つ方法もありますが毎回やるのは手間なので便利です。

構築の手順

1.Docker Toolboxをインストールする

こちらからダウンロードしてください。自分がWindowsなのでWin版でやります。

↑画像の青文字になってる Toolbox Releases からゲットできます。

2.Docker Quickstart Terminalを起動する
無事にインストールできたらDocker Quick Terminalというものがデスクトップにあると思います。起動してください。

3.GitHubからテストアプリをクローン
こちらからクローンしてきたものは適当なところに置いておいてください。

4.VirtualBoxの共有フォルダを設定する
↓画像のようになってDocker Quickstart Terminalが立ち上がっていることが確認できたら、VirtualBoxを起動してください。

VirtualBoxを起動するとDockerホストであるdefaultというマシーンが起動しているので、そのマシーンの共有フォルダを設定してください。
↓例

5.defaultマシーンを再起動する
共有フォルダの設定を有効にするため、Docker Quickstart Terminalに戻ってdefaultマシーンを再起動してください。

Docker_Quickstart_Terminal
$ docker-machine restart default

6.DockerホストのIPアドレスを確認する
Dockerホストdefaultの再起動が完了したら、ホストのIPアドレスを確認します。
MAMPのようにlocalhostでは繋がりませんのでここで確認してください。

Docker_Quickstart_Terminal
$ docker-machine ip default

7.configファイルの編集
万が一IPアドレスが 192.168.99.100 ではないものが出てしまった場合は残念ながら、configファイルの設定をする必要があります。
※通常なら 192.168.99.100 が割り振られるはずなので、当てはまらなかった人は飛ばしてください。

configファイルはGitHubからクローンしてきた中の

app_test/project/app_server/test_app/js/config.js
app_test/project/app_server/test_app/config.php

以上が該当します。
DockerホストのIPが記述されているので、そこをあなたが確認したIPへと編集してください。

config.js
var FQDN='http://192.168.99.100';//<-ここを変える
var TIMEOUT=30000;
config.php
<?php
define('FQDN','http://192.168.99.100');//<-ここを変える
define('DBHOST','mysql');
define('DBPASS','00000');

8.Dockerホストに接続
ここまでの作業が完了したら、DockerホストへとSSH接続します。

Docker_Quickstart_Terminal
$ docker-machine ssh default

9.フォルダが共有されているか確認する

Docker_Quickstart_Terminal
$ ls 自分が設定したパス

クローンしたapp_testなりディレクトリが存在していれば大丈夫です。

10.Docker Composeの存在を確認する
Dockerホストに入ったことを確認したら、まず docker-compose.yml があるところへ移動しましょう。
共有先のフォルダを

/home/docker/app_test

と設定している場合は

Docker_Quickstart_Terminal
$ cd /home/docker/app_test/project

でいけます。この辺のパスは自分の設定したものにしたがってください。
該当ディレクトリのprojectへ移動したら↓

Docker_Quickstart_Terminal
$ docker-compose -v

上記でDocker Composeがインストールされているか確認してください。
おそらく「そんなもの何もない」と言われると思います。
どうやらWin版のDocker ToolboxではDocker Composeまでは用意してくれないようです。Mac版なら用意されていると思います。

11.Docker Composeをインストールする
projectディレクトリに移動できているなら compose-install.sh があるはずです。これを実行すればDocker Composeを手に入れることができます。
※Docker Composeが入っていた方は飛ばしてください。

Docker_Quickstart_Terminal
$ sudo ./compose-install.sh

正常に終了したら再び↓

Docker_Quickstart_Terminal
$ docker-compose -v

バージョンが表示されたらオッケーです。

12.環境をビルドする

下準備が終わったので、Docker Composeでいよいよビルドします。

Docker_Quickstart_Terminal
$ sudo docker-compose up -d

結構時間かかるのでしばらくお待ちください。
ちなみに今回のdocker-compose.ymlはこんな感じです。

docker-compose.yml
version: '3.7'
services:

  app_server:
    build: ./app_server
    image: app_server
    container_name: app_server
    init: true
    volumes:
      - ./app_server/test_app:/var/www/html/test_app
      - ./app_server/favicon/favicon.ico:/var/www/html/favicon.ico
      - ./https_portal/ssl_certs:/var/ssl_certs
      - ./app_server/phpconf/php.ini:/usr/local/etc/php/php.ini
    tty: true
    stdin_open: true
    command: bash -c 'forever start /var/www/html/test_app/mod/app.js && apache2-foreground'
    ports:
      - '80:80'
      - '8080:8080'

  mysql:
    build: ./mysql
    image: mysql:5.7
    container_name: mysql
    init: true
    volumes:
      - ./mysql/app_data:/var/lib/mysql
      - ./mysql/init:/docker-entrypoint-initdb.d
    command: '--innodb_use_native_aio=0'
    environment:
      - MYSQL_ROOT_PASSWORD=00000

  myadmin:
    image: phpmyadmin/phpmyadmin
    container_name: myadmin
    init: true
    environment:
      - PMA_HOST=mysql
    ports:
      - '8000:80'

ミソは

docker-compose.yml
    command: bash -c 'forever start /var/www/html/test_app/mod/app.js && apache2-foreground'

app_serverのcommandの記述です。nodeとapacheの同時起動…ここちょっとはまりました。

↓WEBサーバー用のdockerfile

app_server/dockerfile
FROM php:7.2-apache
RUN curl -L git.io/nodebrew | perl - setup && \
export PATH=$HOME/.nodebrew/current/bin:$PATH && \
nodebrew install v8.9.4 && nodebrew use v8.9.4 && \
npm install -g forever && \
ln -s /root/.nodebrew/node/v8.9.4/lib/node_modules/forever/bin/forever /usr/local/bin/forever && \
cd /root/.nodebrew/current/bin && \
ln -s $PWD/nodebrew /usr/local/bin/nodebrew && \
ln -s $PWD/node /usr/local/bin/node && \
ln -s $PWD/npm /usr/local/bin/npm && \
ln -s $PWD/npx /usr/local/bin/npx
RUN docker-php-ext-install pdo_mysql mysqli mbstring exif fileinfo

↓DB用のdockerfile

mysql/dockerfile
FROM mysql:5.7
ADD ./sqlconf/_my.cnf /etc/mysql/my.cnf
RUN chmod 644 /etc/mysql/my.cnf

13.ブラウザで確認する
configファイルに設定したIPアドレスを参照してブラウザで確認してください。
正常にビルドが完了して特にconfigをいじらなかった場合は以下のアドレスで確認できるはずです。

http://192.168.99.100/test_app/

ログイン画面が表示されたら完了です!
おつかれさまでした。

補足

コンテナの停止と削除

停止コマンド
$ docker-compose stop
または
$ docker stop コンテナ名
コンテナ名は
$ docker ps -a
または
docker-compose.ymlのcontainer_name
で確認できます
削除コマンド
$ docker-compose rm
または
$ docker rm コンテナ名

phpMyAdminに接続

http://192.168.99.100:8000
ID:root
Pass:00000

これで入れます。

テストアプリの構成

まとめ

今回と同じような流れで本番環境にもデプロイできます。
以上、ありがとうございました。

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

alpineで発生する「Error loading shared library ld-linux-x86-64.so.2: No such file or directory」を修正する方法

apk add --no-cahe libc6-compat && ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2

参考

UnsatisfiedLinkError: /tmp/snappy-1.1.4-libsnappyjava.so Error loading shared library ld-linux-x86-64.so.2: No such file or directory

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

5.7 のONLY_FULL_GROUP_BY が出た時にDockerでやった対処

既存のシステムのMySQLを5.6から5.7に変えて動かしたら、group by を使ったSQLでエラーが発生した。

Error Number: 1055

Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 
'dtabase_name.table_name.column_name' which is not functionally dependent on columns in GROUP BY clause; 
this is incompatible with sql_mode=only_full_group_by

このエラーは sql_mode システム変数値に起因するもので、 ONLY_FULL_GROUP_BY が設定されている場合に発生する。
このモードの詳しい説明は 5.1.7 サーバー SQL モード に詳しく記載されている。5.6のマニュアルであるが日本語なので理解しやすい。

例えば GROUP BY 句 に指定がないカラムを SELECT 句 の選択リストに指定するとエラーとなる。

SELECT name, address, MAX(age) FROM t GROUP BY name;

この例の場合は address カラムが GROUP BY 句 に指定がないのでエラーとなる。

sql_mode のデフォルト値

  • 5.6 >= 5.6.6: NO_ENGINE_SUBSTITUTION
  • 5.7: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION

5.7から sql_mode のデフォルト値が変更されたので今回のようなエラーが発生してしまう。

SQLを修正すれば良いが難しいケースもあるので、その場合は sql_mode を変更しよう。

sql_mode の確認方法

MySQLコンソールで以下のように show variables を実行すれば確認できる。

mysql> show variables like 'sql_mode';
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value                                                                                                                                     |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| sql_mode      | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

しかし、ここで表示されるのはSession変数としてのsql_modeなので、Global変数を確認するには別の方法で確認が必要となる。

-- グローバル変数を確認
mysql> select @@global.sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@global.sql_mode                                                                                                                         |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

-- セッション変数を確認
mysql> select @@session.sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@session.sql_mode                                                                                                                        |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

sql_mode のコマンドによる変更

sql_modeset ステートメントで変更することができる。グローバルに変更する場合は global を指定する。

mysql> set global sql_mode='NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select @@GLOBAL.sql_mode;
+------------------------+
| @@GLOBAL.sql_mode      |
+------------------------+
| NO_ENGINE_SUBSTITUTION |
+------------------------+

mysql> select @@session.sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@session.sql_mode                                                                                                                        |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

しかし、グローバル変数を変えただけではセッション変数には反映されない。反映させるには切断して再接続する必要がある。
セッション変数を変える場合は session を指定する。(もしくは何も指定しない)

mysql> set session sql_mode = 'NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected (0.00 sec)

-- または

mysql> set sql_mode = 'NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected (0.00 sec)

mysql> select @@session.sql_mode;
+------------------------+
| @@session.sql_mode     |
+------------------------+
| NO_ENGINE_SUBSTITUTION |
+------------------------+
1 row in set (0.00 sec)

sql_mode の起動パラメーターによる変更

サーバー起動時に --sql-mode="" オプションを使用することで sql_mode を設定できる。

mysqld --sql-mode="NO_ENGINE_SUBSTITUTION"

sql_modemy.cnfによる変更

my.cnfsql-mode="" を指定することで sql_mode を設定できる。

my.cnf
[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

DockerでMySQLコンテナを起動する時に sql_mode を設定するには

起動パラメーターで設定する

docker run コマンドでコンテナを起動する場合は、起動コマンドとして --sql-mode="" を与えることで指定が可能となる。

$ docker run --rm -e MYSQL_ROOT_PASSWORD=root  mysql:5.7 --sql-mode=NO_ENGINE_SUBSTITUTION

DockerComposeの場合も同様に起動コマンドに与えることができる。以下のように docker-compose.ymlcommand: ディレクティブに設定する。

docker-compose.yml
version: '3.7'
services:
  db:
    image: mysql:5.7
    command:
      - --sql-mode=NO_ENGINE_SUBSTITUTION
    environment:
      MYSQL_ROOT_PASSWORD: root

my.cnf で設定する

docker run コマンドで my.cnf をコンテナにわたすにはVolumeとしてマウントする。

docker run --rm -e MYSQL_ROOT_PASSWORD=root -v /path/to/my.cnf:/etc/mysql/conf.d/my.cnf  mysql:5.7

MySQL5.7のコンテナでは /etc/mysql/conf.d/ ディレクトリに任意のファイルを配置することで起動時にロードしてくれる。
また、 MySQLでは複数の my.cnf を順にロードする仕組みがあるのでその中でも順番が遅いファイルにマウントするほうが安全だろう。

my.cnf の読み込み順を確認するには mysql --help | grep 'my.cnf を実行すると確認できる

$  mysql --help  | grep my.cnf
                      order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf

この場合以下の順でロードされるが、/etc/mysql/my.cnf の中で /etc/mysql/conf.d/ をincludeしているので /etc/mysql/conf.d/my.cnf にマウントしてもロードされる。

  • /etc/my.cnf
  • /etc/mysql/my.cnf
  • ~/.my.cnf

DockerComposeの場合は docker-compose.ymlvolumes: ディレクティブに設定できる。

docker-compose.yml
version: '3.7'
services:
  db:
    image: mysql:5.7
    volumes:
      - /path/to/my.cnf:/etc/mysql/conf.d/my.cnf
    environment:
      MYSQL_ROOT_PASSWORD: root
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

簡単にできるDockerイメージのダウンサイジング

概要

Dockerイメージのサイズが大きくなるとレジストリにPushやPullする時間が増します
運用環境や開発環境でイメージのやり取りを繰り返される場合は、回数を重ねるごとにバカにならないほどの待ち時間が発生することになる
また、ネットワーク帯域も無駄に消費します
なので、簡単にできるイメージサイズのダウンサイジングをご紹介します
下記のサンプルでは1.04GBのイメージ ⇒ 415MBまでにダウンサイジングしています
もし、下記以外にもダウンサイジングの方法がありましたら、ご教示ください!

以下のサンプルコードでは、差を分かりやすくするためにあえてjdkをダウンロードし、所有権を変更しています
なお、イメージのリビルド時にキャッシュの有効利用は考慮していません

おさらい

Dockerイメージはビルド時にDockerfileの各コマンドごとに中間イメージが作成される
各中間イメージにはそのコマンドで実行された変更履歴が含まれます
各コマンドが実行され、生成された中間イメージは以下のようになります

最適化していない状態

まず、なにも最適化していないDockerfileでビルドされたイメージサイズは1.04GBもあります!

Dockerfile
FROM node:12-slim

WORKDIR /tmp

RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz
RUN tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz
RUN chown node:node -R /tmp/jdk-12.0.2/

RUN apt-get update -y
RUN apt-get upgrade -y

historyコマンドで中間イメージの容量を確認していきましょう
jdkの取得やファイル解凍で容量を消費しているのはわかりやすいのですが、
chownのようにファイルのメタデータ(所有権)の変更分も容量を消費します
ここは案外見落としがちなポイントです

> docker build -t downsize:1 ./

-----------------------------------------------------------------------------------------------------------
REPOSITORY      TAG                       IMAGE ID            CREATED              SIZE
downsize        1                         e7d7b8b217ba        About a minute ago   1.04GB


> docker history downsize:1

-----------------------------------------------------------------------------------------------------------
IMAGE               CREATED             CREATED BY                                      SIZE
e7d7b8b217ba        2 minutes ago       /bin/sh -c apt-get upgrade -y                   3.85MB
f70cff27b81a        2 minutes ago       /bin/sh -c apt-get update -y                    16.4MB
ce460fc686bc        2 minutes ago       /bin/sh -c chown node:node -R /tmp/jdk-12.0.…   335MB
29b8fb0905ac        2 minutes ago       /bin/sh -c tar -zxvf ./openjdk-12.0.2_linux-…   335MB
39545720b094        3 minutes ago       /bin/sh -c wget https://download.java.net/ja…   198MB
48b8f4c4641a        3 minutes ago       /bin/sh -c #(nop) WORKDIR /tmp                  0B
710340b3b82e        2 months ago        /bin/sh -c #(nop)  CMD ["node"]                 0B
<missing>           2 months ago        /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<missing>           2 months ago        /bin/sh -c #(nop) COPY file:238737301d473041…   116B
<missing>           2 months ago        /bin/sh -c set -ex   && for key in     6A010…   5.08MB
<missing>           2 months ago        /bin/sh -c #(nop)  ENV YARN_VERSION=1.16.0      0B
<missing>           2 months ago        /bin/sh -c buildDeps='xz-utils'     && ARCH=…   90.4MB
<missing>           2 months ago        /bin/sh -c #(nop)  ENV NODE_VERSION=12.6.0      0B
<missing>           2 months ago        /bin/sh -c groupadd --gid 1000 node   && use…   333kB
<missing>           2 months ago        /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 months ago        /bin/sh -c #(nop) ADD file:5ffb798d64089418e…   55.3MB

コマンドをまとめる

各コマンドをすべてひとつのRUNにまとめることで一連のコマンドで発生した履歴も1つになる
中間イメージが減る分容量消費も抑えられる
結果的に300MB減の704MBになりました

Dockerfile
FROM node:12-slim

WORKDIR /tmp

RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
    && tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
    && chown node:node -R /tmp/jdk-12.0.2/ \
    && apt-get update -y \
    && apt-get upgrade -y
> docker build -t downsize:2 ./

-----------------------------------------------------------------------------------------------------------
REPOSITORY      TAG                       IMAGE ID            CREATED              SIZE
downsize        2                         30a607b1a778        About a minute ago   704MB

> docker history downsize:2

-----------------------------------------------------------------------------------------------------------
IMAGE               CREATED             CREATED BY                                      SIZE    
30a607b1a778        2 minutes ago       /bin/sh -c wget https://download.java.net/ja…   553MB
48b8f4c4641a        7 minutes ago       /bin/sh -c #(nop) WORKDIR /tmp                  0B
710340b3b82e        2 months ago        /bin/sh -c #(nop)  CMD ["node"]                 0B
<missing>           2 months ago        /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<missing>           2 months ago        /bin/sh -c #(nop) COPY file:238737301d473041…   116B
<missing>           2 months ago        /bin/sh -c set -ex   && for key in     6A010…   5.08MB
<missing>           2 months ago        /bin/sh -c #(nop)  ENV YARN_VERSION=1.16.0      0B
<missing>           2 months ago        /bin/sh -c buildDeps='xz-utils'     && ARCH=…   90.4MB
<missing>           2 months ago        /bin/sh -c #(nop)  ENV NODE_VERSION=12.6.0      0B
<missing>           2 months ago        /bin/sh -c groupadd --gid 1000 node   && use…   333kB
<missing>           2 months ago        /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 months ago        /bin/sh -c #(nop) ADD file:5ffb798d64089418e…   55.3MB

一時ファイルを削除する

これも忘れがちですが、一時ファイルを削除するだけでサイズ減に繋がる
上記のコマンドに rm -f ./openjdk-12.0.2_linux-x64_bin.tar.gz を追加しただけで、
さらに200MB減の506MBになりました

Dockerfile
FROM alpine

WORKDIR /tmp

RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
    && tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
    && chown postgres:postgres -R /tmp/jdk-12.0.2/ \
    && rm -f ./openjdk-12.0.2_linux-x64_bin.tar.gz

openjdk-12.0.2_linux-x64_bin.tar.gz分のサイズが減った!

> docker build -t downsize:3 ./

-----------------------------------------------------------------------------------------------------------
REPOSITORY      TAG                       IMAGE ID            CREATED              SIZE
downsize        2                         92986480403b        About a minute ago   506MB

> docker history downsize:3
-----------------------------------------------------------------------------------------------------------
IMAGE               CREATED             CREATED BY                                      SIZE
92986480403b        4 seconds ago       /bin/sh -c wget https://download.java.net/ja…   355MB
48b8f4c4641a        9 minutes ago       /bin/sh -c #(nop) WORKDIR /tmp                  0B
710340b3b82e        2 months ago        /bin/sh -c #(nop)  CMD ["node"]                 0B
<missing>           2 months ago        /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<missing>           2 months ago        /bin/sh -c #(nop) COPY file:238737301d473041…   116B
<missing>           2 months ago        /bin/sh -c set -ex   && for key in     6A010…   5.08MB
<missing>           2 months ago        /bin/sh -c #(nop)  ENV YARN_VERSION=1.16.0      0B
<missing>           2 months ago        /bin/sh -c buildDeps='xz-utils'     && ARCH=…   90.4MB
<missing>           2 months ago        /bin/sh -c #(nop)  ENV NODE_VERSION=12.6.0      0B
<missing>           2 months ago        /bin/sh -c groupadd --gid 1000 node   && use…   333kB
<missing>           2 months ago        /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 months ago        /bin/sh -c #(nop) ADD file:5ffb798d64089418e…   55.3MB

これだと減らないので注意!

コマンドを分けることでIMAGE ID:30a607b1a778の結果は553MBのままなので、そのまま中間イメージとして加算される

Dockerfile
FROM node:12-slim

WORKDIR /tmp

RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
    && tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
    && chown node:node -R /tmp/jdk-12.0.2/ \
    && apt-get update -y \
    && apt-get upgrade -y

RUN rm -f ./openjdk-12.0.2_linux-x64_bin.tar.gz
> docker build -t downsize:3.1 ./

-----------------------------------------------------------------------------------------------------------
REPOSITORY      TAG                       IMAGE ID            CREATED              SIZE
downsize        3.1                       4ee2a610be24        About a minute ago   704MB

> docker history downsize:3.1
-----------------------------------------------------------------------------------------------------------
IMAGE               CREATED             CREATED BY                                      SIZE
4ee2a610be24        About a minute ago   /bin/sh -c rm -f ./openjdk-12.0.2_linux-x64_…   0B
30a607b1a778        8 minutes ago        /bin/sh -c wget https://download.java.net/ja…   553MB
48b8f4c4641a        13 minutes ago       /bin/sh -c #(nop) WORKDIR /tmp                  0B
710340b3b82e        2 months ago         /bin/sh -c #(nop)  CMD ["node"]                 0B
<missing>           2 months ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<missing>           2 months ago         /bin/sh -c #(nop) COPY file:238737301d473041…   116B
<missing>           2 months ago         /bin/sh -c set -ex   && for key in     6A010…   5.08MB
<missing>           2 months ago         /bin/sh -c #(nop)  ENV YARN_VERSION=1.16.0      0B
<missing>           2 months ago         /bin/sh -c buildDeps='xz-utils'     && ARCH=…   90.4MB
<missing>           2 months ago         /bin/sh -c #(nop)  ENV NODE_VERSION=12.6.0      0B
<missing>           2 months ago         /bin/sh -c groupadd --gid 1000 node   && use…   333kB
<missing>           2 months ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 months ago         /bin/sh -c #(nop) ADD file:5ffb798d64089418e…   55.3MB

マルチステージング化

今回のサンプルでは残念ながらサイズ減にはならなかったが、
中間イメージサイズの起算が COPY --from=base /tmp/jdk-12.0.2 /tmp/jdk-12.0.2になりますので、
事前処理であれこれ(ソースのコンパイルなど)した場合は、マルチステージング化することで簡単に容量減に繋がります

Dockerfile
FROM node:12-slim as base

WORKDIR /tmp

RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
    && tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
    && chown node:node -R /tmp/jdk-12.0.2/

FROM node:12-slim

COPY --from=base /tmp/jdk-12.0.2 /tmp/jdk-12.0.2

RUN apt-get update -y \
    && apt-get upgrade -y
> docker build -t downsize:4 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY      TAG                       IMAGE ID            CREATED              SIZE
downsize        4                       593b49b2ed5e        About a minute ago     506MB

> docker history downsize:4
-----------------------------------------------------------------------------------------------------------
IMAGE               CREATED             CREATED BY                                      SIZE
593b49b2ed5e        12 minutes ago      /bin/sh -c apt-get update -y     && apt-get …   20.3MB
f5659402be7a        12 minutes ago      /bin/sh -c #(nop) COPY dir:523c1f51e78e02aa1…   335MB
710340b3b82e        2 months ago        /bin/sh -c #(nop)  CMD ["node"]                 0B
<missing>           2 months ago        /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<missing>           2 months ago        /bin/sh -c #(nop) COPY file:238737301d473041…   116B
<missing>           2 months ago        /bin/sh -c set -ex   && for key in     6A010…   5.08MB
<missing>           2 months ago        /bin/sh -c #(nop)  ENV YARN_VERSION=1.16.0      0B
<missing>           2 months ago        /bin/sh -c buildDeps='xz-utils'     && ARCH=…   90.4MB
<missing>           2 months ago        /bin/sh -c #(nop)  ENV NODE_VERSION=12.6.0      0B
<missing>           2 months ago        /bin/sh -c groupadd --gid 1000 node   && use…   333kB
<missing>           2 months ago        /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 months ago        /bin/sh -c #(nop) ADD file:5ffb798d64089418e…   55.3MB

パッケージマネージャのキャッシュを削除

これも忘れがちなのですが、パッケージマネージャのキャッシュを削除することで容量減に繋がります
さらに20MB減の490MBになりました

Dockerfile
FROM node:12-slim as base

WORKDIR /tmp

RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
    && tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
    && chown node:node -R /tmp/jdk-12.0.2/

FROM node:12-slim

COPY --from=base /tmp/jdk-12.0.2 /tmp/jdk-12.0.2

RUN apt-get update -y \
    && apt-get upgrade -y \
    && apt-get autoremove -y \
    && apt-get clean -y \
    && rm -rf /var/lib/apt/lists/*
> docker build -t downsize:5 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY      TAG                       IMAGE ID            CREATED              SIZE
downsize        5                       6de3a6ddead6          About a minute ago   490MB

> docker history downsize:5
-----------------------------------------------------------------------------------------------------------
IMAGE               CREATED              CREATED BY                                      SIZE
6de3a6ddead6        About a minute ago   /bin/sh -c apt-get update -y     && apt-get …   3.85MB
f5659402be7a        12 minutes ago       /bin/sh -c #(nop) COPY dir:523c1f51e78e02aa1…   335MB
710340b3b82e        2 months ago         /bin/sh -c #(nop)  CMD ["node"]                 0B
<missing>           2 months ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<missing>           2 months ago         /bin/sh -c #(nop) COPY file:238737301d473041…   116B
<missing>           2 months ago         /bin/sh -c set -ex   && for key in     6A010…   5.08MB
<missing>           2 months ago         /bin/sh -c #(nop)  ENV YARN_VERSION=1.16.0      0B
<missing>           2 months ago         /bin/sh -c buildDeps='xz-utils'     && ARCH=…   90.4MB
<missing>           2 months ago         /bin/sh -c #(nop)  ENV NODE_VERSION=12.6.0      0B
<missing>           2 months ago         /bin/sh -c groupadd --gid 1000 node   && use…   333kB
<missing>           2 months ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 months ago         /bin/sh -c #(nop) ADD file:5ffb798d64089418e…   55.3MB

スリムなベースイメージを使う

上記のサンプルだとベースイメージにDebian系を使用していますが、超軽量なAlpine Linuxを使用することで劇的にサイズ減が図れます
ただし下記のnode:12-alpineはNode.js込みのため、さほどサイズ減につながりませんが、素のAlpine Linuxだと5.53MB !

Dockerfile
FROM node:12-alpine as base

WORKDIR /tmp

RUN wget https://download.java.net/java/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_linux-x64_bin.tar.gz \
    && tar -zxvf ./openjdk-12.0.2_linux-x64_bin.tar.gz \
    && chown node:node -R /tmp/jdk-12.0.2/

FROM node:12-alpine

COPY --from=base /tmp/jdk-12.0.2 /tmp/jdk-12.0.2

RUN apk update \
    && apk upgrade \
    && rm -rf /var/cache/apk/*
> docker build -t downsize:6 ./
-----------------------------------------------------------------------------------------------------------
REPOSITORY      TAG                       IMAGE ID            CREATED              SIZE
downsize        6                       2389f4627226          About a minute ago   415MB

> docker history downsize:5
-----------------------------------------------------------------------------------------------------------
IMAGE               CREATED              CREATED BY                                      SIZE
2389f4627226        About a minute ago   RUN /bin/sh -c apk update     && apk upgrade…   22.1kB
<missing>           About a minute ago   COPY /tmp/jdk-12.0.2 /tmp/jdk-12.0.2 # build…   335MB
<missing>           3 days ago           /bin/sh -c #(nop)  CMD ["node"]                 0B
<missing>           3 days ago           /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<missing>           3 days ago           /bin/sh -c #(nop) COPY file:238737301d473041…   116B
<missing>           3 days ago           /bin/sh -c apk add --no-cache --virtual .bui…   5.5MB
<missing>           3 days ago           /bin/sh -c #(nop)  ENV YARN_VERSION=1.17.3      0B
<missing>           3 days ago           /bin/sh -c addgroup -g 1000 node     && addu…   69.3MB
<missing>           3 days ago           /bin/sh -c #(nop)  ENV NODE_VERSION=12.10.0     0B
<missing>           4 months ago         /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           4 months ago         /bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6a…   5.53MB
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【2019年9月版】台風も直撃して通勤もままならないので BASIC でプログラマの本能を呼び起そうか

Docker で N88-BASICを動かしてみたい!

いや、流石に N88-BASICそのものは動かないよね・・・と言うことで何か近い環境があるのかないのか調べてみました。

そして以下のサイトを発見しまして〜

"Bywater BASIC" というのが N88BASICに近いみたい?!
以下の記事も発見。bwbasic、生きてるみたいです!
- Qitta:bwBASICでBASIC言語に再会してみよう

というわけで・・・apt install してみますか。docker で。

早速、Docker Play Ground サイトでインスタンス作成し、docker run -it ubuntu bash からの apt update && apt upgrade して〜の(というかこの辺りお決まりコースなのでなんとか省力化できないかな・・・)、apt install bwbasicしてみます!

root@d889abd9355f:/# apt install bwbasic
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  bwbasic
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 83.6 kB of archives.
After this operation, 288 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu bionic/universe amd64 bwbasic amd64 2.20pl2-11build1 [83.6 kB]
Fetched 83.6 kB in 0s (227 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package bwbasic.
(Reading database ... 4040 files and directories currently installed.)
Preparing to unpack .../bwbasic_2.20pl2-11build1_amd64.deb ...
Unpacking bwbasic (2.20pl2-11build1) ...
Setting up bwbasic (2.20pl2-11build1) ...
root@d889abd9355f:/# bwbasic
Bywater BASIC Interpreter/Shell, version 2.20 patch level 2
Copyright (c) 1993, Ted A. Campbell
Copyright (c) 1995-1997, Jon B. Volkoff

bwBASIC: 
bwBASIC: 
bwBASIC: print "aaa"
aaa
bwBASIC: quit

root@d889abd9355f:/# 

print文が動くっ!動くぞコイツっ!!

と言うわけで、dockerfile 仕立てておきました。はい。

ついでにDockerfileはこんな感じです。

FROM ubuntu

RUN apt update && \
    apt -y upgrade && \
    apt -y install bwbasic lhasa

ARG program_dir=/root/program

VOLUME $program_dir

WORKDIR $program_dir

・・・適当ですいません。

docker の使える環境で

$ docker run -it dcyossyjp/bwbasic bash

としていただければbwbasicと lzhの解凍ができるlhaコマンドが使える環境に入れます。

lha コマンドは以下の記事が参考になるでしょうか。

それでは以下のサイトのプログラム動かしてみよかな〜

http://www5f.biglobe.ne.jp/~apaslothy/prog80/basicmagazine/index.html

そのほか、"マイコンBASICマガジン"、"ベーマガ 掲載プログラム" などで検索するとお宝が発掘できるかもしれません?!(雑誌に掲載されたプログラムは再配布とか色々アレなのでQiitaでは掲載を自粛致しますw 各自、個人の趣味の範囲でお楽しみください。。。)

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

GitHub Actions v2 で Packer ビルドする

はじめに

Packer で AWS AMI をビルドする方法について調べていると各自のローカル環境で実行するのを前提に実行ファイルをダウンロードすることが多いようです。
少し試すだけならローカルから実行で十分なのですが、継続的なビルドを考えると環境差異が生じたり場合によってはローカルに接続先 AWS 設定が複数あったりして安全ではないように思えます。
そこで GitHub Actions を使い、安定した環境で実行できるようにします。

Packer や GitHub Actions (まだベータなので申請が必要)がどういうものかについての説明は割愛します。
10分で理解するPackerGitHub ヘルプ をお読みください。

コード

.github/workflows/packer.yml
name: Packer
on:
  push:
      paths:
        - '*.json'
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: packer validate packer.json
        uses: docker://hashicorp/packer:1.4.3
        with:
          args: validate packer.json
      - name: packer build packer.json
        uses: docker://hashicorp/packer:1.4.3
        with:
          args: build packer.json
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-1
packer.json
{
    "builders": [
        {
            "type": "amazon-ebs",
            "source_ami_filter": {
                "filters": {
                    "virtualization-type": "hvm",
                    "name": "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*",
                    "root-device-type": "ebs"
                },
                "owners": [
                    "099720109477"
                ],
                "most_recent": true
            },
            "instance_type": "t2.micro",
            "ssh_username": "ubuntu",
            "ami_name": "packer-example {{timestamp}}"
        }
    ]
}

解説

packer.json

Packer の設定ファイルです。ファイル名は任意。
AMI 定義は Build an Image - Getting Started - Packer by HashiCorp のファイルをお借りします。中身の説明は割愛。
環境変数で渡す部分は削除しています。

.github/workflows/packer.yml

.github/workflows/ ディレクトリにファイルを作成します。ファイル名は任意。

name: Packer

Actions タブに表示される名前です。任意の文字列。

on:
  push:
      paths:
        - '*.json'

トリガー です。実際はもう少し複雑な条件になると思います。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1

GitHub Actions に用意されている ubuntu イメージで実行します。( Packer の実行は Docker コンテナで行うので ubuntu じゃなくても大丈夫なはずです。)
Packer の設定ファイルを参照したいのでコードもチェックアウトしておきます。

      - name: packer validate packer.json
        uses: docker://hashicorp/packer:1.4.3
        with:
          args: validate packer.json

まずは packer validate します。エラーになるとここで終了します。
GitHub Actions では専用に定義されたアクションだけでなく Docker コンテナイメージをアクションに使用できます。
hashicorp/packer - Docker Hub を使います。
ENTRYPOINT に bin/packer が設定されているので args には validate 以降を渡します。
現時点の latest である 1.4.3 を指定していますがお好みで。

ワークフローを設定する - GitHub ヘルプ によるとアクションは以下の3つが使えます。

  • パブリックリポジトリ
  • ワークフローファイルがアクションを参照するのと同じリポジトリ
  • Docker ハブで公開されている Docker コンテナイメージ
      - name: packer build packer.json
        uses: docker://hashicorp/packer:1.4.3
        with:
          args: build packer.json
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-1

エラーにならなければ packer build します。
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY はログに出力されると困るのでリポジトリの Settings > Secrets に設定します。

実行結果

コードは GitHub に公開していますのでこちらから実行結果を確認できます。
SnowCait/github-actions-packer-example@2d76fe9

おわりに

Qiita へは初投稿になります。
最初の記事は何を書こうかな?と思っていたのですが、ちょうど GitHub Actions のベータ申請が通ったのと Packer を触る機会があり課題を抱えていたので実装してみました。
GitHub Actions には期待しているので今後も記事を書いていこうと思っています。
ネタがあったらコメントいただけると嬉しいです。

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

CodeBuildでECRビルドエラーから得た4つの知見

はじめに

ECRをただビルドしたかった...はじめて使うといろいろハマりポイントが多くてたくさん調べる羽目に
自分自身が次ハマらないようにまとめておく。

TL;DR

  • 1.aws/codebuild/standard:2.0 を使用するときは runtime-versions を指定する必要がある
  • 2.ビルドを実行するロールにECRを操作するポリシーを追加する必要がある
  • 3.Dockerの特権付与チェックを入れる必要がある
  • 4.ECRの「プッシュコマンドの表示」をよく見て環境変数を設定する

4つのエラー詳細と対応方法

1.aws/codebuild/standard:2.0 を使用するときは runtime-versions を指定する必要がある

YAML_FILE_ERROR: This build image requires selecting at least one runtime version.
  • 今回はDockerを利用していたため以下の設定をbuildspec.ymlに追記する必要があった。
buildspec.yml
phases:
  install:
    runtime-versions:
      docker: 18

2.ビルドを実行するロールにECRを操作するポリシーを追加する必要がある

COMMAND_EXECUTION_ERROR: Error while executing command: $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION). Reason: exit status 255
  • デフォルトではECRのポリシーは設定されていない。
  • 自分で設定を追加する必要がある
  • IAMでロールにAmazonEC2ContainerRegistryPowerUser(ECRの操作を許可する)ポリシーをアタッチ

3.Dockerの特権付与チェックを入れる必要がある

[Container] 2019/09/07 17:00:26 Running command docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG . 
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 
  • Dockerデーモンが起動していないようなエラーが発生
  • CodeBuildは実行自体がDocker(Ubuntuなど選択)だが、その中でDockerを使うため、チェックが必要になる
  • Docker in Dockerのような実行Docker(Ubuntu)の上でECRをBuildするためのDockerが動作しているイメージ

4.ECRの「プッシュコマンドの表示」をよく見て環境変数を設定する

[Container] 2019/09/07 17:32:13 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: docker push
$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG. Reason: exit status 1 
  • アカウントIDの環境変数にずっとIAMユーザー名を入れるミスをしていた。
  • ECRの「プッシュコマンドの表示」にプッシュに必要な環境変数の設定サンプルがあるので確認する
  • 隠した部分をよく見れば、アカウントIDだと気がつくことができた
  • ちなみにbuildにつかったbuildspec.ymlはこちら。
  • 原始的だが、echoでログを出していく事もミス発見に繋がった。
buildspec.yml
version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - echo $IMAGE_REPO_NAME
      - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
      - echo docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
      - printf '[{"name":"<container-definition>","imageUri":"%s"}]' $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG > artifacts.json

artifacts:
  files: artifacts.json

さいごに

  • ECRのbuild&pushを行うときのハマりポイントは理解さえすれば二度とハマらない内容でした。
  • 手動より楽なことを実感できたのでパイプライン等と組み合わせてどんどん最適化していきたいです。
  • こちらのブログにもAWS関連いくつか記事を書き始めました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【メモ】DockerでNode.jsが使えるコンテナの一覧を見たいときに便利なリンク

非常に便利なページなのですが、ブックマークが見られない環境のためにここに書いておきます。

node - Docker Hub

このページは簡単に言うと、

nodejsがもともと入ってる、Docker公式のDockerfileリンク一覧

ってことになります(ちなみにリンク先はGithubで管理されてるDockerfile)。

あとは、このページに書かれているリンクをDockerfileのFROM文として追加すればOKです。

FROM 12.10.0-alpine

これであとはDokcer本やDockerサイトを参考に環境を整えられればと思います。

おまけ

中にはDBが欲しいという方もいらっしゃいますので、その時のためにMySQLとPostgreSQLのリンク集も載せておきます。

mysql - Docker Hub

postgres - Docker Hub

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