20200318のdockerに関する記事は13件です。

WSL2,Docker,Studio 3tではまったところ

win10で、WSL2,Docker,Studio 3Tを使用した時にStudio 3TからDocker上のmongodbに繋げなくて、はまったことについて書きます。

WSL2はlocalhostではない。

基本的なことですが、WSL2をlocalhostだと思っていました。なので、Stdio 3TでCONNECTのhost sererをlocalhost(初期値)に設定して繋げようとしたのですが、「Cnnecting to server」がfalseになって、つながりませんでした。

そこで、下記の事を行いました。

①WSL2のubuntuのipアドレスを知る。
 ubuntuで下記コマンドをたたいて、ipアドレスを知ります。

$ hostname -I

②Studio 3Tのconnectionのseverに①で調べたipアドレス(192.168.0,0みたいなもの)を入力

これでつながりました。

補足ですが、STUDIO 3tでデータをIntelliShellで作成したが、すぐには反映されず、Studio 3Tを再起動しなければ作成したデータが見れませんでした。何かwin10で使用する際に癖があるのでしょうか?

以上です。

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

Sequel Proに接続できなかったときの備忘録

はじめに

dockerで起動したmysqlコンテナSequel Proの接続が出来なかったので備忘録として記録します。

設定

docker-compose.yml
#一部抜粋
db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"
SequelPro
名前:local(任意)
ホスト:127.0.0.1
ユーザ名:root
パスワード:password
ポート:3306

接続できずにエラー発生。

image.png

ググる。
ポート番号がすでにローカルで使われているかもしれない!という記事にたどり着く。
dockerで起動したmysqlコンテナにsequel proで接続する

ポートの確認

ポート番号の確認をしてみる。(portscanを実行する)
ローカルで使用されているポート番号の調べ方はこちらの記事を参考にしました。
Macで使用しているポートを調べる方法とポートを使用しているプログラム確認方法

以前にローカルで使用した
mysqlですでに3306番が使われていることが発覚!

ポート番号の変更

docker-compose.yml
#一部抜粋
db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "4306:3306"     ←←変更

変更後、再度docker-compose buildをやりなおしコンテナを立ち上げ、Sequel Proへの接続が無事に成功しました。

締め

いろいろ調べていくとmysql8.0にするとSequelProへの接続がエラーになったという情報もちらほら見られた。mysql8.0は現時点では情報量も少ないので、mysql5.7の方が扱いやすいかもですね。

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

Azuriteでローカル環境構築(Docker + PHP + Azure Storage)

目的

Azuriteを利用してDocker + PHP + Azure Storageのローカル環境を構築します。
Dockerによるローカル環境構築を進めてきましたがStorageはAzureプラットフォームのを利用していたので、Azuriteを利用してローカル環境だけで完結させます。

Azuriteとは

Azure Storageのエミュレーター。

ローカルでの Azure Storage の開発とテストに Azurite エミュレーターを使用する (プレビュー)

AzuriteかAzure ストレージ エミュレーターか

Azurite は今後のストレージ エミュレーター プラットフォームです。Azurite は Azure ストレージ エミュレーターよりも優先されます。

ということなので今後もこちらを使っていけば良さそうです。

Azuriteのインストール方法

  1. Azurite Docker イメージをインストールして実行する

今回はDockerを利用するのでこちらを選択します。

Docker環境

Azurite - Docker Hub

docker-compose.yml

version: '3'

services:
  php:
    # 省略

  storage:
    image: mcr.microsoft.com/azure-storage/azurite
    prots:
      - "10000:10000"
    volumes:
      - ./docker/storage/data:./data

PHPのコンテナについては割愛します。
公式のPHPライブラリ を利用してAzure Storageを利用できればAzuriteに関しても問題ないと思ってます。

また、今回はBlobだけを使用するのでTableとQueueについても割愛します。

Azure Storage Explorerから接続してみる

Azure Storage Explorer

接続ダイアログから「ローカル エミュレーターにアタッチする」を選択してアタッチします。

AzuriteにBlobを作成する

phpでBlobを作成していきます。

<?php
require_once '../vendor/autoload.php';

$connection = '<接続文字列>';
$client = \MicrosoftAzure\Storage\Blob\BlobRestProxy::createBlobService($connection);

$container = 'sample'; // 事前に作成しておく
$blob = 'example.txt';
$content = 'Hello Azurite!';

$client->createBlockBlob($container, $blob, $content);

接続文字列について

$connection = 'UseDevelopmentStorage=true';

基本はこのショートカットでOK。
しかしDocker環境だと事情が異なります。
これで先程の処理を実行しようとすると・・・

cURL error 7: Failed to connect to 127.0.0.1 port 10000

Dockerコンテナ間で接続する場合、これでは不十分のようです。
先程のショートカットを展開した接続文字列からエンドポイントを変更していきます。

BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1

ここのホスト名をコンテナのサービス名に変更します。

BlobEndpoint=http://storage:10000/devstoreaccount1

最終的な接続文字列は次の通りです。

$connection = 'DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;
AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;
BlobEndpoint=http://storage:10000/devstoreaccount1;';

AccountName、AccountKeyはエミュレーター固定です。
TableEndpoint、QueueEndpointは割愛します。

これで先程のBlob作成処理を実行すると・・・

explorer.png

作成されました。

パブリックURLが・・・

ひとつ問題が残りました。

// http://storage:10000/devstoreaccount1/sample/example.txt
echo $client->getBlobUrl($container, $blob);

接続文字列でホスト名をコンテナのサービス名にしたのはDockerコンテナ間で接続するためでした。
コンテナ外のブラウザからアクセスする場合は「127.0.0.1」にしなければならないです。
(パブリックアクセスの設定を変更して許可するのも忘れずに)

Docker + Azurite + ブラウザからアクセスするケース(例えばHTMLのaタグ、imgタグ等)はホスト名を書き換えなければいけません。

まとめ

微妙な部分もありましたがローカル環境としては十分だと思ってます。
「ちょっと動かすだけなのに、AzureプラットフォームにStorage
サービスを作成しないといけない」という点は解消できました。

問題等(追記)

使ってるなかで気がついた問題などです。

Append Blob がサポートされていない

リリース「2020.03 Version 3.6.0」時点です。

We will consider Append Blob in the future, but it's still not in the recent release plan.

https://github.com/Azure/Azurite/issues/271

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

GitHub ActionsでOpenAPI Generatorを動かす [Docker版]

TL;DR

API定義ファイルが更新されたらGitHub ActionsでOpenAPI Generatorを動かしてPRを作る

用意するもの

  1. OpenAPI-Specification v3に準拠したAPI定義ファイル
  2. API定義ファイルを管理するリポジトリ
  3. 生成したクライアントを管理するリポジトリ

GitHub Actionsで動かすOpenAPI Generator

本編です

1. sample-openapiの用意

  1. GitHub Actionsを作成
generate.yaml
# This is a basic workflow to help you get started with Actions

name: generate

# Controls when the action will run. Triggers the workflow on push or pull request 
# events but only for the master branch and petstore.yaml
on:
  push:
    branches: [ master ]
    paths: petstore.yaml

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - uses: actions/checkout@v2

    # clientをcheckout
    - uses: actions/checkout@v2
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        repository: yumemi-nkomiya/github-actions-client-openapi
        path: client

    # openapi generate
    - uses: docker://openapitools/openapi-generator-cli
      with:
        args: generate -i ./petstore.yaml -g swift5 -o ./client/

    # Create pull request
    - uses: peter-evans/create-pull-request@v2
      with:
        token: ${{ secrets.REPO_ACCESS_TOKEN }}
        path: client
        commit-message: update client
        title: update client
        body: update client
        branch: feature/update_client
        branch-suffix: short-commit-hash # 同じプルリクは作らない

解説

  • trigger

ブランチとファイルを条件指定

  • clientをcheckout

client-openapiをチェックアウトします。
client-openapiがprivateならPersonal access tokenを作ってsample-openapiのsecretsに登録して使います

  • openapi generate

mavenビルドしてとか、jarをリポジトリに入れてとかあったんだけど公式にDockerが提供されているので利用する
パラメータはargsに指定します

  • Create pull request

client-openapiの権限があるPersonal access tokenが必要

2. GitHub Actionsの実行

sample-openapiにpetstore.yamlをpush

  • GitHub Actionsの実行結果

https://github.com/yumemi-nkomiya/github-actions-sample-openapi/actions/runs/57991712)

  • 作成されたPR

https://github.com/yumemi-nkomiya/github-actions-client-openapi/pull/1


おまけ

generatorがpodspecやPackage.swiftを生成してくれるのでCocoaPodsや、tag打つだけでSwiftPMやCarthageも対応できます


参考記事

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

Docker + CentOS8でrailsアプリをデプロイするまで

はじめに

CentOS8で自作したrailsアプリをdocker nginx unicornでデプロイするまでを、つまづいたことなど含めて備忘録として書いていきます(時系列順に書いているので少し遠回りな手順になってます)
Dockerについては、動きを把握するためにDockerfileを使わずに動かしてます

環境

ruby 2.5.1
(Rails 5.2.3)
CentOS8

まずはDockerのところから

% docker run -d -it -p 3000:80 --name myapp centos:8
docker exec -it myapp bash

これでCentOSのコンテナを立ち上げてnginxをインストールして、systemctlで起動しようとしたら、D-Busだのnot permittedみたいなエラーが出て怒られた

どうやら、CentOS7でも同じようなことが起こるみたい。こちらを参照した

コンテナを削除して、もう一度立ち上げる

% docker rm myapp
% docker run -d -it -p 3000:80 --privileged --name myapp centos:8 /sbin/init
% docker exec -it myapp bash

--privilegedオプションについてはこちらを参照

これでsystemctlコマンドが使えているはずです

必要なソフトウェアをインストールしていく

nginxの動作確認

# systemctl
# dnf install -y git vim nginx
# systemctl start nginx
# systemctl status nginx
# vim /etc/nginx/nginx.conf
# vim /usr/share/nginx/html
# vim /usr/share/nginx/html/index.html

Rubyのインストール

anyenv→rbenvから今回使うruby2.5.1をインストールする

anyenvのインストールについては公式のwikiから

# git clone https://github.com/anyenv/anyenv ~/.anyenv
# echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile
# ~/.anyenv/bin/anyenv init
# vim .bash_profile          →eval "$(anyenv init -)"を記述
# exec $SHELL -l
# anyenv install --init
# anyenv -v

# anyenv install rbenv
# exec $SHELL -l

rbenvを入れるところまではできたが、rubyを入れるところから少し躓いた

# rbenv install 2.5.1
Downloading ruby-2.5.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.bz2
/root/.anyenv/envs/rbenv/plugins/ruby-build/bin/ruby-build: line 213: pushd: ruby-2.5.1: No such file or directory

BUILD FAILED (CentOS Linux 8 using ruby-build 20200224)

Inspect or clean up the working tree at /tmp/ruby-build.20200302084110.884.8HpNM1
Results logged to /tmp/ruby-build.20200302084110.884.log

Last 10 log lines:
/tmp/ruby-build.20200302084110.884.8HpNM1 ~
warning: bzip2 not found; consider installing `bzip2` package
tar (child): bzip2: Cannot exec: No such file or directory
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now

どうやらtarやbzip2が入ってないと言われ怒られたようです

# dnf install tar bzip2 -y

もう一回チャレンジ

[root@32a991428119 ~]# rbenv install 2.5.1
Downloading ruby-2.5.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.bz2
Installing ruby-2.5.1...

BUILD FAILED (CentOS Linux 8 using ruby-build 20200224)

Inspect or clean up the working tree at /tmp/ruby-build.20200302084353.1066.LCm1tD
Results logged to /tmp/ruby-build.20200302084353.1066.log

Last 10 log lines:
checking for ruby... false
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: in `/tmp/ruby-build.20200302084353.1066.LCm1tD/ruby-2.5.1':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

今度はCコンパイラがないと言われてるから、それをインストールしてみる
(この後、makeもなかったようなのでmakeもインストール)

# dnf install gcc make
ERROR: Ruby install aborted due to missing extensions
Try running `yum install -y openssl-devel readline-devel zlib-devel` to fetch missing dependencies.

また怒られた。。。
さらにインストール

# dnf install -y openssl-devel readline-devel zlib-devel
# rbenv install 2.5.1
Downloading ruby-2.5.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.bz2
Installing ruby-2.5.1...
Installed ruby-2.5.1 to /root/.anyenv/envs/rbenv/versions/2.5.1
# ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]

できた!

Rails アプリのclone

作ったアプリをgithubリポジトリからクローン
今回は自分が作ったアプリをcloneしていきます。この部分は任意のURLに置き換えてください

# git clone https://github.com/xxx/hogehoge.git

⚠️Gemfile.lockのbundler のバージョンによってはgem install bundlerするだけじゃエラーが起こるから注意!

こんなエラーが起こることがある

# gem install bundler
Fetching: bundler-2.1.4.gem (100%)
Successfully installed bundler-2.1.4
Parsing documentation for bundler-2.1.4
Installing ri documentation for bundler-2.1.4
Done installing documentation for bundler after 4 seconds
1 gem installed
# bundle install
Traceback (most recent call last):
    2: from /root/.anyenv/envs/rbenv/versions/2.5.1/bin/bundle:23:in `<main>'
    1: from /root/.anyenv/envs/rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems.rb:308:in `activate_bin_path'
/root/.anyenv/envs/rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems.rb:289:in `find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)

gemfile.lockのBUNDLED WITHにあるバージョンをインストールする
参考

# gem install bundler -v 2.0.1

これでbundle installコマンドも使えているはず

unicornとnginxの設定

unicornの設定についてはこちら

unicorn.rbのlisten, pidと、lib/tasks/unicorn.rbのdef unicorn_pidは各自の環境で設定しておくこと

このままrake unicorn:startコマンドをしてみると、Could not find a JavaScript runtime.と怒られます(JavaScript入れるの忘れてました)

ということでjavaScriptの動作環境を得るためにnode.jsをインストール。これもanyenvからインストール

# anyenv install -l    →nodenvがあったからそれを入れます
# anyenv install nodenv
# exec $SHELL -l
# nodenv install 12.16.1
# nodenv global 12.16.1
# exec $SHELL -l
# node -v
=>v12.16.1

また、この時点でsqlite3が入ってないときでもエラーになったから、入れておく
エラーの内容はlog/unicorn.logで確認できるよ!sqliteのヘッダファイルがなかったらしい?

# dnf install -y sqlite
# dnf install sqlite-devel.x86_64 →sqliteをインストールするだけじゃgemインストールできず、Development toolsが必要だった(dnf search sqliteしてみた)
# gem install sqlite3 -v '1.3.13' --source 'https://rubygems.org/'

これでちゃんとrake unicorn:startが動いた!

あとは参考サイトのnginxの設定通りに進めていく。
・・・が、いざnginxの再起動をすると、正常に画面が出なくなった(403 Forbbidenが出てた)
エラーログをみてみる

% tail /var/log/nginx/error.log
2020/03/02 11:04:28 [crit] 54612#0: *2 connect() to unix:/root/Workspace/ikea_stock_finder/tmp/unicorn.sock failed (13: Permission denied) while connecting to upstream, client: 172.17.0.1, server: _, request: "GET / HTTP/1.1", upstream: "http://unix:/root/Workspace/ikea_stock_finder/tmp/unicorn.sock:/500.html", host: "localhost:3000"

どうやら権限がないらしい。ps aux | grep unicornでプロセスをみてみるとrootで実行されている。nginx.confの設定ではuserはnginxとなっているからここがおかしいのか?と思いrootに変えてみたら、うまくできました

最後に

一度コンテナから抜け出した後に再び% docker exec -it myapp bashでログインしたら、bash_profileが読み込まれていないらしい?
% docker exec -it myapp bash --loginとすると解決

当たり前ですが今の状態でdocker stopした後にdocker startすると、nginxやunicornの再起動が必要です

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

OpenAPIを使ってモックサーバーを起動する

OpenAPIを使ってAPI定義を書いている場合、その定義ファイルからモックのサーバーが起動できれば便利ですよね。
実際にAPIサーバーの実装が完了する前からクライアント側の実装を行うことができるので、とても効率が良いです!

調べれば色々と方法が出てきますが、個人的に楽だった方法をまとめておきます。

Prismがめちゃくちゃ便利

stoplight社のprismというOSSのモックサーバーを使います。
今回はこのDockerイメージを使うので、Dockerを入れていない場合は先に入れておいてください。

openapi.yamlの準備

まずはAPI定義を行った openapi.yaml を準備してください。
今回は、例としてシンプルな内容の定義ファイルを用意しました。

openapi.yaml
openapi: 3.0.0
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
components:
  schemas:
    Pet:
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
          example: 1
        name:
          type: string
          example: "pochi"
        tag:
          type: string
          example: "dog"
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    Error:
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string

モックサーバーの起動

先程用意した openapi.yaml と同じディレクトリ内で、下記を実行します。
これだけです!

docker run --rm -it -p 4010:4010 -v $PWD:/tmp stoplight/prism:3 mock -h 0.0.0.0 /tmp/openapi.yaml

実際にAPIを叩いてみます。

curl 'localhost:4010/pets'

レスポンスとして、 openapi.yamlexample で定義した内容が返ってきます。

[
  {
    "id": 1,
    "name": "pochi",
    "tag": "dog"
  }
]

ちなみに、 -d オプションを使うと、レスポンスが動的に変わります。

docker run --rm -it -p 4010:4010 -v $PWD:/tmp stoplight/prism:3 mock -h 0.0.0.0 -d /tmp/openapi.yaml

レスポンスはこの様に、毎回変わります。

[
  {
    "id": 8872624476737700000,
    "name": "Duis",
    "tag": "magna in laborum"
  },
  {
    "id": -6385831628202697000,
    "name": "veniam in do fugiat irure",
    "tag": "consequat Ut Excepteur anim tempor"
  },
  {
    "id": 4943733727999074000,
    "name": "dolor dolor",
    "tag": "dolore pariatur ullam"
  },
  {
    "id": -1524702861247148000,
    "name": "irure voluptate dolor mollit ex",
    "tag": "quis"
  }
]

本当に簡単ですね!

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

Docker環境にSystem Specを導入する

はじめに

Docer環境でRSpecのSystem Specを導入しようとしたところ、結構ハマったので、備忘録としてまとめます。

まず、Docer環境にSystem Specを実行するためには、いくつか方法があるらしい。
調査をしていると、メジャーな方法は以下の二つ(もっとあるかもしれませんが、、、)

1. Railsが動いているimageにchromeをインストールする方法
2. chrome用コンテナを立ち上げる方法

今回は2の方法でやってみました。

前提

Quickstart: Compose and Railsの通りに、Rails on Dockerの環境構築が済んでいる状態とします。
筆者の環境は
- Ruby 2.5.7
- Rails 5.2.4
です。

docker-compose.ymlを編集する

selenium_chromeのコンテナが立ち上がるようdocker-compose.ymlに追加していきます。
Dockerイメージにはselenium/standalone-chromeを使用します。

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
      #追加
      - chrome
  #追加
  chrome:
    image: selenium/standalone-chrome:3.141.59-dubnium
    ports:
      - 4444:4444

gemを追加する

Gemfile
group :development, :test do
  gem 'rspec-rails'
end

group :test do
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
end

dockerをbuildして、bundle installします。

$ docker-compose build
$ docker-compose up -d

rspecの設定

rspecをインストールします。

$ docker-compose run web rails g rspec:install

headless chromeの設定

spec/rails_helper.rbにheadless chromeの設定を追加していきます。

/spec/rails_helper.rb
require 'capybara/rspec'

# headless chrome 設定①
Capybara.server_host = Socket.ip_address_list.detect { |addr| addr.ipv4_private? }.ip_address
Capybara.server_port = 3001   

Capybara.register_driver :selenium_remote do |app|
  url = "http://chrome:4444/wd/hub"
  opts = { desired_capabilities: :chrome, browser: :remote, url: url }
  Capybara::Selenium::Driver.new(app, opts)
end


 # headless chrome 設定②
RSpec.configure do |config|

  config.before(:each, type: :system) do
    driven_by :rack_test
  end

  config.before(:each, type: :system, js: true) do
    driven_by :selenium_remote
    host! "http://#{Capybara.server_host}:#{Capybara.server_port}"
  end
end

ポイント:
後半部分(# headless chrome 設定②)で、
js: trueを記述した場合のみ、seleniumドライバーが立ち上がるように設定しています。

ハマったポイント:
js: trueのテストを走らせたとき、Capybaraがseleniumサーバーを立ち上げて、先ほど設定したchromeコンテナで起動しているchromeを操作します。
しかし、Capybara.server_portを指定する部分(*)で、webコンテナで指定したポートと同じ3000を指定してしまうと、js: trueのテストを走らせたときに、webコンテナで指定したポートと競合してseleniumサーバーが立ち上がらずエラーとなってしまいます。
そこで、Capybara.server_port = 3000 3001
とすることで、競合することなく、無事サーバーが立ち上がり、テストが通るようになりました。

これで準備は整いました。
あとは、テストを実際に走らせるだけです。

実際にテストを走らせてみる

spec/system/test_spec.rb
require "rails_helper"

RSpec.describe 'Test', type: :system, js: true do
  example 'サンプルテスト' do
    #ここにテスト内容を記述
  end
end
$ docker-compose exec web bundle exec rpsec

これで、テストが通るはずです。

参考記事

下記の記事を参考にさせていただきました。
ありがとうございます。
- Docker で RSpec の System Spec を実行するための設定メモ
- Rails + Selenium + DockerでSystemSpecの環境構築
- Rails on Dockerにて、Headless ChromeでSystem Testをやってみた。

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

laravel on dockerのimage別速度比較

目的

php:fpm-alpineイメージを使ってlaravelを動かしていましたところ、異様にレスポンスが遅かったので調べてみたところこんな話がありました。
https://qiita.com/yoshiken/items/93d170b69d8cb8520bad

どうやらalpineが遅いと。
そこでイメージの選択でどれくらい違いが出るのかを試してみました。

比較対象

  • alpine
  • debian
  • centos

比較方法

laravel newした直後のプロジェクトをphp artisan serveで起動し、以下の2パターンで比較してみました。

  • /(Welcomページ)へリクエスト
  • /items(itemモデルとレコード100件を作って一覧をjsonで返す)へリクエスト

測定にはsiegeを利用しています。

比較結果

$ siege --no-follow -r 10 -c 1 http://localhost:8000
image response time(s)
debian 0.31
alpine 0.77
centos 0.81
$ siege --no-follow -r 10 -c 1 http://localhost:8000/items
image response time(s)
debian 0.19
alpine 1.90
centos 1.67

意外とcentosでも遅い結果になりました。
原因は何なのでしょうね?alpineとcentosでは動かすためにインストールしたExtensionが似ていたので、Extensionの違いだったりするんでしょうか。。

参考

Dockerfile

debian
FROM debian
RUN apt-get update
RUN apt-get install -y php
RUN apt-get install -y php-zip
RUN apt-get install -y php-mbstring
RUN apt-get install -y php-dom
RUN apt-get install -y php-mysql
WORKDIR /app
alpine
FROM alpine
RUN apk update
RUN apk add php
RUN apk add php-zip
RUN apk add php-mbstring
RUN apk add php-dom
RUN apk add php-phar
RUN apk add php-json
RUN apk add php-openssl
RUN apk add php-session
RUN apk add php-mysqlnd
RUN apk add php-pdo
RUN apk add php-pdo_mysql
COPY php.ini /etc/php7/php.ini
WORKDIR /app
centos
FROM centos
RUN yum update -y
RUN yum install -y php
RUN yum install -y php-mbstring
RUN yum install -y php-dom
RUN yum install -y php-json
RUN yum install -y php-session
RUN yum install -y php-mysqlnd
RUN yum install -y php-pdo
RUN yum install -y php-pdo_mysql
COPY php.ini /etc/php.ini
WORKDIR /app
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

alpine + laravel on dockerのimage別速度比較

目的

php:fpm-alpineイメージを使ってlaravelを動かしていましたところ、異様にレスポンスが遅かったので調べてみたところこんな話がありました。
https://qiita.com/yoshiken/items/93d170b69d8cb8520bad

どうやらalpineが遅いと。
そこでイメージの選択でどれくらい違いが出るのかを試してみました。

比較対象

  • alpine
  • debian
  • centos

比較方法

laravel newした直後のプロジェクトをphp artisan serveで起動し、以下の2パターンで比較してみました。

  • /(Welcomページ)へリクエスト
  • /items(itemモデルとレコード100件を作って一覧をjsonで返す)へリクエスト

測定にはsiegeを利用しています。

比較結果

$ siege --no-follow -r 10 -c 1 http://localhost:8000
image response time(s)
debian 0.31
alpine 0.77
centos 0.81
$ siege --no-follow -r 10 -c 1 http://localhost:8000/items
image response time(s)
debian 0.19
alpine 1.90
centos 1.67

意外とcentosでも遅い結果になりました。
原因は何なのでしょうね?alpineとcentosでは動かすためにインストールしたExtensionが似ていたので、Extensionの違いだったりするんでしょうか。。

参考

Dockerfile

debian
FROM debian
RUN apt-get update
RUN apt-get install -y php
RUN apt-get install -y php-zip
RUN apt-get install -y php-mbstring
RUN apt-get install -y php-dom
RUN apt-get install -y php-mysql
WORKDIR /app
alpine
FROM alpine
RUN apk update
RUN apk add php
RUN apk add php-zip
RUN apk add php-mbstring
RUN apk add php-dom
RUN apk add php-phar
RUN apk add php-json
RUN apk add php-openssl
RUN apk add php-session
RUN apk add php-mysqlnd
RUN apk add php-pdo
RUN apk add php-pdo_mysql
COPY php.ini /etc/php7/php.ini
WORKDIR /app
centos
FROM centos
RUN yum update -y
RUN yum install -y php
RUN yum install -y php-mbstring
RUN yum install -y php-dom
RUN yum install -y php-json
RUN yum install -y php-session
RUN yum install -y php-mysqlnd
RUN yum install -y php-pdo
RUN yum install -y php-pdo_mysql
COPY php.ini /etc/php.ini
WORKDIR /app
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerのMySQLコンテナが、永遠に再起動を繰り返すエラーの対処法

概要

事象

MySQLが動くDockerコンテナを、docker-composeで立ち上げようとしたところ、コンテナが永遠に再起動を繰り返す事象が起こりました。この問題の解決方法を、ここにメモしておきます。

ちなみに、私はWindows上でDocker Toolboxを用いていた時にこの問題が起こりましたが、それ以外の環境だとこの問題は起こらなさそうです(おそらく)。

docker-compose.ymlの設定

docker-compose.ymlのうち、この問題が起こる部分の設定は以下のようになっています。

  db:
    image: mysql:5.7
    volumes: 
      - "/tmp/db/data:/var/lib/mysql"
      - "./db:/usr/src/db"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
      MYSQL_DATABASE: $MYSQL_DATABASE
      MYSQL_USER: $MYSQL_USER
      MYSQL_PASSWORD: $MYSQL_PASSWORD
    ports:
      - 3306:3306

特別な設定は何もしておらず、単純にmysql:5.7のイメージをベースに必要最低限の設定をしているのみです。

対処法

立ち上がったコンテナ内で、--innodb-use-native-aio=0を実行させます。なので、docker-compose.ymlは以下のようになります。

  db:
    image: mysql:5.7
    volumes: 
      - "/tmp/db/data:/var/lib/mysql"
      - "./db:/usr/src/db"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
      MYSQL_DATABASE: $MYSQL_DATABASE
      MYSQL_USER: $MYSQL_USER
      MYSQL_PASSWORD: $MYSQL_PASSWORD
    ports:
      - 3306:3306
     command: --innodb-use-native-aio=0 # <- これ!

なぜこれで解決するのか

MySQLの公式ドキュメントには、以下のような記述があります。

InnoDB uses the asynchronous I/O subsystem (native AIO) on Linux to perform read-ahead and write requests for data file pages. This behavior is controlled by the innodb_use_native_aio configuration option, which applies to Linux systems only and is enabled by default.

InnoDB(MySQLのためのデータベースエンジン)はデフォルトでLinuxの非同期I/O(native AIO)を用いるように設定されていますが、この挙動はinnodb_use_native_aioオプションで変更できます。

今回私はWindows上でDocker Toolboxを用いてコンテナを動かしていたのですが、その場合だとこの非同期I/Oが利用できないため、エラーが起こり再起動が繰り返されていたようです。そのため、公式ドキュメントの上に引用した部分に書いてある通り、innodb_use_native_aioオプションで非同期I/Oを用いないように設定して、この問題を回避する必要があります。

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

DockerのMySQLコンテナが、Docker Toolbox上で起動に失敗するエラーの対処法

概要

事象

MySQLが動くDockerコンテナを、docker-composeで立ち上げようとしたところ、コンテナが永遠に再起動(restart)を繰り返す事象が起こりました。この問題の解決方法を、ここにメモしておきます。

ちなみに、私はWindows上でDocker Toolboxを用いていた時にこの問題が起こりましたが、それ以外の環境だとこの問題は起こらなさそうです(おそらく)。

docker-compose.ymlの設定

docker-compose.ymlのうち、この問題が起こる部分の設定は以下のようになっています。

  db:
    image: mysql:5.7
    volumes: 
      - "/tmp/db/data:/var/lib/mysql"
      - "./db:/usr/src/db"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
      MYSQL_DATABASE: $MYSQL_DATABASE
      MYSQL_USER: $MYSQL_USER
      MYSQL_PASSWORD: $MYSQL_PASSWORD
    ports:
      - 3306:3306

特別な設定は何もしておらず、単純にmysql:5.7のイメージをベースに必要最低限の設定をしているのみです。

対処法

立ち上がったコンテナ内で、--innodb-use-native-aio=0を実行させます。なので、docker-compose.ymlは以下のようになります。

  db:
    image: mysql:5.7
    volumes: 
      - "/tmp/db/data:/var/lib/mysql"
      - "./db:/usr/src/db"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
      MYSQL_DATABASE: $MYSQL_DATABASE
      MYSQL_USER: $MYSQL_USER
      MYSQL_PASSWORD: $MYSQL_PASSWORD
    ports:
      - 3306:3306
     command: --innodb-use-native-aio=0 # <- これ!

なぜこれで解決するのか

MySQLの公式ドキュメントには、以下のような記述があります。

InnoDB uses the asynchronous I/O subsystem (native AIO) on Linux to perform read-ahead and write requests for data file pages. This behavior is controlled by the innodb_use_native_aio configuration option, which applies to Linux systems only and is enabled by default.

InnoDB(MySQLのためのデータベースエンジン)はデフォルトでLinuxの非同期I/O(native AIO)を用いるように設定されていますが、この挙動はinnodb_use_native_aioオプションで変更できます。

今回私はWindows上でDocker Toolboxを用いてコンテナを動かしていたのですが、その場合だとこの非同期I/Oが利用できないため、エラーが起こり再起動が繰り返されていたようです。そのため、公式ドキュメントの上に引用した部分に書いてある通り、innodb_use_native_aioオプションで非同期I/Oを用いないように設定して、この問題を回避する必要があります。

コンテナの再起動について

コンテナが再起動するのは、私がdocker-compose.ymlにrestart:alwaysを書いているからです。それ以外の場合は、普通にコンテナが落ちると思われます。

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

dockerコンテナにサブドメインなどもまとめて1つのIPに名前解決する

やりたいこと

  1. docker-composeで立ち上げたコンテナから任意のホストに名前解決したい
  2. docker-networkには参加させない(E2EテストやブラウザでURLを打ってアクセスさせるなど)
  3. かつ、サブドメインで同じIPに名前解決したい

// TODO: つまりどういうことだってばよ (説明する)

2までの場合

例として、uyu.pun ドメインを192.168.1.11に受け流すように変更してみます。

// TODO: extra_hostsが何をしているのか

docker-compose.yml
version: '3'
services:
  app:
    image: node:13.10.1
    ports:
      - 3000:3000
    # ↓ 足す
    extra_hosts:
      - 'uyu.pun:192.168.1.11'
    command: "node app.js"
    volumes:
      - ./:/src
    working_dir: /src

参考: Docker で Node.js 開発環境を簡単に用意する
ポートについては固定値に変更させていただきました。

↓コンテナ立ち上げ後、シェルで /etc/hosts ファイルを参照した結果です。(他の項目は省いています)

/etc/hosts
192.168.1.11 uyu.pun

鬼の仕様変更

…ではないと思いますが、サブドメインで同じホストの別ポートにマッピングしたい、といった状況になったとします。

例として、admin.uyu.pun も192.168.1.11に向けてみます。

docker-compose.yml
version: '3'
services:
  app:
    image: node:13.10.1
    ports:
      - 3000:3000
    # 失敗する
    extra_hosts:
      - 'uyu.pun:192.168.1.11'
      - 'admin.uyu.pun:192.168.1.11'
    command: 'node app.js'
    volumes:
      - ./:/src
    working_dir: /src

↓出力後

/etc/hosts
192.168.1.11 uyu.pun
192.168.1.11 admin.uyu.pun

この状態でpingを打つと失敗します。どうもhostsファイルの仕様っぽいです。
参考: Hostsファイル:複数の行に同じIPアドレスがあるのは間違っていますか?
ざっくりとしか読んでいませんが、先に書いたほうが優先される?模様。

対策 : コロンより前をスペース区切りで記述する

docker-compose.yml
version: '3'
services:
  app:
    image: node:13.10.1
    ports:
      - 3000:3000
    # コロンより前をスペース区切りで記述する
    extra_hosts:
      - 'uyu.pun admin.uyu.pun:192.168.1.11'
    command: 'node app.js'
    volumes:
      - ./:/src
    working_dir: /src

↓起動後の /etc/hostsファイルの確認

/etc/hosts
192.168.1.11    uyu.pun admin.uyu.pun

pingを打ってみます。

 # ping uyu.pun
PING uyu.pun (192.168.1.11) 56(84) bytes of data.
From 192.168.1.22 (192.168.1.22) icmp_seq=1 Destination Host Unreachable
^c
# ping admin.uyu.pun
PING uyu.pun (192.168.1.11) 56(84) bytes of data.
From 192.168.1.22 (192.168.1.22) icmp_seq=1 Destination Host Unreachable

無事、2つのドメインを同じIPに名前解決できた。(IPアドレスは適当にしたので疎通できていませんが、期待したIPにpingを投げていることがわかると思います。)

応用

今回これを試したのは、なるべく実運用に近い環境でE2Eテストの実行をしたいという背景でした。
各自のローカルマシンのdockerコンテナ上にあるサーバーにリクエストを向けるために、IPアドレスの部分は変数にし、参照元の.envファイルは以下のようにし .gitignoreしています。
ちなみに、.envの環境変数を展開する場合は"で囲うようです。

docker-compose.yml
...
extra_hosts:
  - "uyu.pun admin.uyu.pun:${HOST_MACHINE_IP}"
...
.env
HOST_MACHINE_IP=192.168.1.11

課題

記入するドメインが増えると横に長くなっていってしまうので、ymlファイル上では改行してきれいに表示したい。。

おわりに

uyu.punって何?うゆぷん?って方へ
こちら

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

Linux(Ubuntu,CentOSなど)にDockerを入れる便利なスクリプト

Docker公式が便利なスクリプトを用意してくれている。
毎回インストール後に思い出すのでメモ。

https://docs.docker.com/install/linux/docker-ce/ubuntu/
の下のほうに書いてある。

# インストールスクリプトをダウンロードして実行
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# 非rootユーザーで実行したい場合に
# 一回ログアウトしないと反映されない
sudo usermod -aG docker your-user

# docker-composeも使う場合に
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

また、公式のドキュメントには、
- プロダクション環境で使うのはお勧めしない
- sudo権限で動くスクリプトのため、実行前に内容を確認しておくこと
などと書かれてある。

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