20190820のdockerに関する記事は8件です。

System specを使えるRuby on Rails開発環境をDockerで作る

Railsチュートリアルの2周目を、Docker環境でかつテストをRspecに代えて進めていたのですが、System specを導入しようとしたところで挫折…。
いろいろ調べたり、指導者の方に聞いたりして解決しましたので、同じように迷っている人の為になればと思い、書き残してみます。

そもそもSystem specとはなんぞや?

System specについて知らない人はこちらの記事が参考になると思います。
rspec-rails 3.7の新機能!System Specを使ってみた

簡単に説明すると、エンドツーエンド(E2E)テストを実行するための機能です。みなさんが実際にブラウザを利用するようにボタンやリンクを押してどの画面に遷移しただとか、その画面にはある特定のHTMLタグが含まれているかどうかなどをテストすることができます。
使ってみればわかると思いますが、とてもわかりやすく便利です。

ちなみに、System specはrspec-rails 3.7以降から導入されたのですが、その前はFeature specというのが使われていました。実はほとんど同じなので、Feature specで進めても良いのですが、公式で推奨されているのでSystem specを使ってみたいと思います。

System(Feature) specで使えるいろいろな機能は以下の記事を参考にしてください。
使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」

さらにそもそもRSpecやDockerに詳しくない方へ

RSpec→使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」
Docker→【図解】Dockerの全体像を理解する -前編-
※ Dockerがインストールされていることを前提に話を進めますので、忘れずにインストールしておいてくだい。

では、本題に入りましょう。
ちなみに、一から作成していくので、すでにRailsでDocker環境を持っている人は適宜置き換えて試してみてください。

docker-composeを用いてRails Projectを作成する

完成版をおいておきます。
https://github.com/tegnike/system_spec

ではまず、以下のファイルを作成しましょう。

  • Dockerfile
  • docker-compose.yml
  • Gemfile
  • Gemfile.lock

RailsのDocker環境作成に関しては以下の記事を参考にしています。
docker-compose で Rails の開発環境を作る

Dockerfile
FROM ruby:2.4.2
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev postgresql-client unzip
RUN sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -' && \
    sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' && \
    apt-get update && apt-get install -y google-chrome-stable
RUN mkdir /app

WORKDIR /tmp
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN bundle install

ADD . /app
WORKDIR /app

System specではGoogle Chromをインストールしておく必要があるので、3行目のRUNでそれを実行しています。

docker-compose.yml
db:
  image: postgres
  expose:
    - "5432"
web:
  build: .
  command: bundle exec rails s -p 3000 -b '0.0.0.0'
  volumes:
    - .:/app
  ports:
    - "3000:3000"
  links:
    - db
Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 5.1.4'
Gemfile.lock

Gemfile.lockは中身は空のまま、ファイルだけ作成ください。
ちなみに、Dockerfileの3行目のRUNでsystem specに必要なGoogle Chromeをwebコンテナにインストールしています。

これらのファイルが用意できたら、それらがあるフォルダで以下のコマンドを実行してください。

$ docker-compose run web rails new . --force --database=postgresql --skip-test

このコマンドを実行することで、docker-compose.ymlに定義したwebコンテナを一時起動し、Rails Projectを作成することができます。

フォルダ下にRailsのファイルたちが追加されていますね。
では、更新されたGemfileにrspecでのテストに必要な下記のgemを追記しましょう。

Gemfile
gem 'therubyracer', platforms: :ruby # 先頭の"#"を消す

### 省略 ###

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console |
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] # 元から書いてあります
  gem 'rspec-rails' # 追記
end

group :test do
  gem 'capybara' # 追記
  gem 'selenium-webdriver' # 追記
  gem 'webdrivers' # 追記
  gem 'launchy', '~> 2.4.3' # 追記
end

では、更新したGemfileをimageに含めるためにbuildを実行しましょう。

$ docker-compose build

次に、database.ymlを編集します。
今回はデータベースにpostgresqlを使用するので、以下のように設定してください。

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  username: postgres # 追記
  host: db # 追記
  password: # 追記

以下のコマンドでデータベースを作成します。

$ docker-compose run web rake db:create

これで一通り準備が整いましたので、下記のコマンドでコンテナを立ち上げてから localhost:3000 にアクセスすれば、お馴染みのYay! You're on Rails!を見ることができます。

$ docker-compose up -d

System specを導入する

では、System specを導入していきましょう。
まず、下記のコマンドを実行することでRSpecの設定ファイルである spec_helper.rbrails_helper.rb の2つのファイルが作成されます。

$ docker-compose run web rails generate rspec:install

そして rails_helper.rb は以下のように修正してください。

spec/rails_helper.rb
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] = 'test'
require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
require 'capybara/rspec'
# Add additional requires below this line. Rails is not loaded until this point!

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

# Checks for pending migrations and applies them before tests are run.
# If you are not using ActiveRecord, you can remove these lines.
begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end
RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  # RSpec Rails can automatically mix in different behaviours to your tests
  # based on their file location, for example enabling you to call `get` and
  # `post` in specs under `spec/controllers`.
  #
  # You can disable this behaviour by removing the line below, and instead
  # explicitly tag your specs with their type, e.g.:
  #
  #     RSpec.describe UsersController, :type => :controller do
  #       # ...
  #     end
  #
  # The different available types are documented in the features, such as in
  # https://relishapp.com/rspec/rspec-rails/docs
  config.infer_spec_type_from_file_location!

  # Filter lines from Rails gems in backtraces.
  config.filter_rails_from_backtrace!
  # arbitrary gems may also be filtered via:
  # config.filter_gems_from_backtrace("gem name")
  config.before(:each, type: :system) do
    driven_by :selenium_chrome
  end

  config.before(:each, type: :system, js: true) do
    driven_by :selenium_chrome
  end
end

もう1つ、 capybara.rb というファイルを作ります。これはまだ作成されていないので、specフォルダの下にsupportファイルを作り、その下に配置しましょう。

spec/support/capybara.rb
Capybara.default_driver    = :selenium_chrome
Capybara.javascript_driver = :selenium_chrome

Capybara.register_driver :selenium_chrome do |app|
  options = ::Selenium::WebDriver::Chrome::Options.new

  options.add_argument('--headless')
  options.add_argument('--no-sandbox')
  options.add_argument('--disable-gpu')
  options.add_argument('--window-size=1400,1400')

  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

これでSystem specの設定は完了です。

System specでテストしてみよう!

せっかく作ったので試してみたいのですが、今のままだとモデルがなくてテストができないので、 scaffold コマンドでUserモデルを作成します。ついでにマイグレーションも実行しましょう。

※ ちなみに今回はSystem specが動くかどうか確認することを目的としていますので、複雑なテストは書きません。

$ docker-compose run web bin/rails g scaffold User name:string
$ docker-compose run web rake db:migrate

specフォルダ下にSystem spec用のフォルダを作成し、そこに users_spec.rb を作成します。

spec/system/users_spec.rb
require 'rails_helper'

RSpec.describe 'Users', type: :system, js: true do
  before do
    @user = User.create!(name: 'Test User')
  end

  it 'ユーザ名が表示されること' do
    visit user_path(@user)

    expect(page).to have_content @user.name
  end
end

では、テストを実行してみましょう。

$ docker-compose up
$ docker-compose run web rspec spec/system/users_spec.rb
Starting system_spec_db_1 ... done
.

Finished in 5.18 seconds (files took 4.95 seconds to load)
1 example, 0 failures

はい、問題なく成功しました!

まとめ

この記事では、System Specを使えるDocker環境の構築を説明しました。
冒頭でも説明しましたが、Feature Specとほとんど一緒のSystem Specですが、確実に上位互換なので導入しておいて損はないでしょう(公式でも推奨されていますしね)。

では、また。

参考

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

DockerでCPUの使用量制限をする(--cpus)

概要

Dockerには使えるCPUのコア(スレッド)数を制限する機能があります。

0.1コア分だけ使用する
docker update --cpus 0.1 container 
docker create -it --cpus 4.5 --storage-opt size=120G fedora /bin/bash

最小単位が0.01から、最大で搭載しているコアの数まで上げられます。
これと言って特定のコアにやらせるわけではないので、OSが勝手に実際に使うコアを指定します。

docker updateの場合には即座に制限が有効になるようです。

仕組み

例えば、

docker update --cpus 0.1 container 

とした場合、

docker inspect container 
・・・
"HostConfig": {
 "NanoCpus": 100000000,
・・・

とされます。

NanoCPU つまり

100000000 NanoCPU = 0.1 CPUコア

という等式が成り立ちます。

NanoCPUというのは

CPU quota in units of 10-9 CPUs.

1CPUを109区切りにした値のようです。
ところが、なぜこのような奇妙な分け方をするのは明らかではありません。
小数点を入れないようにするためでしょうか。

関連記事

参考文献

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

ローカルにDockerレジストリを建てる

レジストリのコンテナを起動

docker run -d -p 5000:5000 --restart=always --name registry registry:2

タグをつけてpushする

$ docker tag sample:0.1.0 localhost:5000/sample
$ docker push localhost:5000/sample
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CircleCIで複数のイメージを利用する場合の注意点

発生した事象

CICDフローにおいて、CircleCi上でrspecを実行するために準備としてrails db:createを実行した。
しかし、実行中にDB接続エラーが発生した。

結論

CircleCIのジョブ実行において複数のイメージ指定する場合、DBの接続ホスト指定はlocalhostを指定ではなく127.0.0.1を使おう。

失敗時のエラーメッセージ

rails aborted!
Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 "No such file or directory")

良くあるrailsからDBへの接続エラーですね。   
ローカルのmysqlを参照しにいこうとしている様子。

現状の設定見直し

接続エラーなので、DBの接続情報の設定を見直してみる。

Circleciのconfig.yml

接続コマンドや環境変数やRAILS_ENVも適切で問題なさそう。

Ruby on Railsで利用している database.yml

設定ファイル上に、DB接続ホスト、ユーザ名、DB名が指定してあるため接続には問題なさそう。

調査

調査を進めると次の記事にヒットしました。

また、各コンテナ間の連携には localhost を使うことはできません。 127.0.0.1 を指定するようにすることと、Rails であれば config/database.yml で以下のような記述を追加することを忘れないようにしましょう。
https://tech.smarthr.jp/entry/2017/07/12/073000

対応

上記の記事より、本件も同一事象と仮定しrailsで指定しているDBのhost指定を、localhostではなく、127.0.0.1に変更し動作確認。

jobの確認

#!/bin/bash -eo pipefail
bundle exec rails db:create
bundle exec rails db:migrate
bundle exec rspec
Created database 'hoge'
(中略)
Finished in 0.00373 seconds (files took 0.87988 seconds to load)

実行も完了し、ジョブも正常終了したのでOK!。

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

DockerでGitLab

古くなったGitLabサーバを刷新することになった。
折角なのでDockerでやってみた。

Docker定義

web:
  image: 'gitlab/gitlab-ce:latest'
  restart: always
  container_name: 'gitlab'
  hostname: 'xxx.yyy.com'
  environment:
    GITLAB_OMNIBUS_CONFIG: |
      external_url 'http://xxx.yyy.com/gitlab'
  ports:
    - '10080:80'
    - '10443:443'
    - '10022:22'
  volumes:
    - '/srv/gitlab/config:/etc/gitlab'
    - '/srv/gitlab/logs:/var/log/gitlab'
    - '/srv/gitlab/data:/var/opt/gitlab'

特に工夫はない。ポートを既存のものと被らないようにしただけ。
volumesはパスを変えたらうまく動作しなかった気がする?
メモリは4GBでやっと動いた。そこそこリソースは必要みたいです。

起動まで時間がかかるので、起動しきったかを以下のコマンドで確認した。

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

Docker×Python×Oracle-CloudでLINE Botを作ってみた。 #2

はじめに

Flask×PythonでBotのアルゴリズムを作り、dockerの乗せてリモートサーバ稼働させる流れをまとめたものです。

第1回(前回)は、
python3の記述までの内容を扱いました。

今回は、
Dockerfileの作成からリモートサーバでのデプロイまでの内容を扱います。

目次

実装環境

環境

  • MacOS X 10.13.6 (local)
  • Docker 18.09.2

Docker

{$PWD}/Dockerfileを作成します。

Dockerfile
# ベースとなるイメージを指定する
FROM ubuntu:latest

# コンテナ上のワーキングディレクトリを指定する
WORKDIR /usr/src/

# ディレクトリやファイルをコピーする
# 左側がホストのディレクトリ、右側がコンテナ上のディレクトリ
COPY ./src /usr/src
COPY ./startup.sh /startup.sh

# "docker build"時に実行される処理
RUN apt-get update
RUN apt-get install python3 python3-pip -y
RUN pip3 install flask
RUN pip3 install line-bot-sdk
RUN pip3 install python-dotenv
RUN chmod 744 /startup.sh
RUN echo "building..."

# "docker run"実行時に実行される処理
CMD /startup.sh

また、docker runでstartup.shを実行しますが、内容はこんな感じです。

startup.sh
# 日本語扱えるようにする
export LC_CTYPE=C.UTF-8
# flask run!!
python3 /usr/src/app.py

リモートサーバ

以下のコマンドを実行します。
これからはリモートサーバでの作業になります。

$ scp . user@server:~/
$ ssh user@server:~/docker-bot

$ (sudo) docker build -t bot .
# 割と時間かかる

これで、dockerの準備は完了です。
あとはLINEサーバとの接続と docker run すればbotが動きそうです。

Webhootの設定

LINEサーバとの接続をするためには、Webhookの設定をする必要がありますが、https通信以外は弾かれてしまいます。
その打開策として、今回はngrokを使います。
参考: ngrokが便利すぎる

ngrokを実行({ngrok directory}/ngrok http {port})すると以下のような画面が表示されます。
Forwardingのhttpsのアドレス(この場合はad19992.a.ngrok.io)をあとで使います。
また、このアドレスはngrokを実行するたびにランダムで変更されます。

ngrok
ngrok by @inconshreveable                      (Ctrl+C to quit)

Session Status                online                           
Session Expires               7 hours, 59 minutes              
Version                       2.3.34                           
Region                        United States (us)               
Web Interface                 http://127.0.0.1:4040            
Forwarding                    http://ad19992a.ngrok.io -> http:
Forwarding                    https://ad19992a.ngrok.io -> http

Connections                   ttl     opn     rt1     rt5     p
                              0       0       0.00    0.00    0

tmux

サーバ上ではdockerとngrokをマルチに開いておく必要があるので、今回はtmuxを採用します。
参考: tmuxを必要最低限で入門して使う

tmuxで実現するイメージ
server
├ docker-run
└ ngrok
server
$ tmux new -s docker-run
$ (sudo) docker run -it --rm -p 8000:8000 bot

# ウィンドウからデタッチ
ctrl + b, d

$ tmux new -s ngrok
$ {ngrok directory}/ngrok http 8000
# line devloperの設定を行う
ctrl + b, d

# サーバからログアウトしてもdocker-run, ngrokは停止しない。
$ exit

LINE Devloperの
「TOP > プロバイダーリスト > {プロバイダー名} > {botのアカウント名} > チャネル基本設定」で、
メッセージ送受信設定の「Webhook送信」を「利用する」に変更した後、
Forwardingのhttpsのアドレスをコピーして、「Webhook URL」に貼り付けます。
最終的には Webhook URL がhttps://ad19992.a.ngrok.io/callbackになるようにします。

以上で、botにラインを送った時の返信が変更されます。

おわりに

ngrokとflaskはdocker-composeでまとめられそうだけど、docker-compose分からないので、その辺りは追々学ぼうと思いました。

参考

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

Ubuntu18.04/Re:VIEW/docker-compose/zathuraを使って薄い本を書く手順

モチベーション

  • 素早く薄い本を書くぞ!
  • なるたけ楽するぞ!

使用するもの

  • Docker(仮想環境を簡単/便利に扱えるツール)
  • docker-compose(複数の仮想環境を簡単に扱えるツール)
  • Re:VIEW(軽量マークアップ言語からpdf(latex), epubなどの書籍が簡単に作れるツール)
  • zathura(vimのキーバインドが使える軽量PDFビューアー)

手順

1. Re:VIEWのDockerイメージをダウンロードする

bash
$ sudo docker pull vvakame/review

2. 薄い本の雛形を作成する

bash
$ cd
$ sudo docker run --rm -v `pwd`:/work vvakame/review /bin/sh -c "cd /work && review-init hello"

3. docker-composeを使ってpdfファイルを作成する

bash
$ cd

# 所有権を変更する
$ sudo chown -R solareenlo:solareenlo hello

$ cd hello

# Dockerfileを作成する
$ echo FROM vvakame/review > Dockerfile

# docker-compose.ymlを作成する
$ cat <<EOF > docker-compose.yml 
version: '3'
services:
  review:
    volumes:
      - .:/work
    build: .
    working_dir: /work
EOF

# pdfファイルを作成する
$ sudo docker-compose run review rake pdf

4. zathuraで作成したPDFを確認する

bash
$ sudo apt install zathura
$ zathura --fork book.pdf

5. いろいろ削除する

bash
# pdf作成過程で出来た不要なコンテナを削除する
$ sudo docker container prune

# Re:VIEWのDockerイメージを削除する
$ sudo docker image rm vvakame/review:latest

# zathuraを削除する
$ sudo apt uninstall zathura

あとは好きなエディタとドキュメントを見ながら作成する

参考文献

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

Ubuntu18.04/Re:VIEW/docker-compose/zathuraを使った薄い本を書く手順

モチベーション

  • なるたけ楽して$LaTeX$使って薄い本を書く.
  • ホスト環境を変更せずに素早く薄い本を書く.

使用するもの

  • Docker(仮想環境を簡単/便利に扱えるツール)
  • docker-compose(複数の仮想環境を簡単に扱えるツール)
  • Re:VIEW(軽量マークアップ言語からpdf(latex), epubなどの書籍が簡単に作れるツール)
  • zathura(vimのキーバインドが使える軽量PDFビューアー)

手順

1. Re:VIEWのDockerイメージをダウンロードする

bash
$ sudo docker pull vvakame/review

2. 薄い本の雛形を作成する

bash
$ cd
$ sudo docker run --rm -v `pwd`:/work vvakame/review /bin/sh -c "cd /work && review-init hello"

3. docker-composeを使ってpdfファイルを作成する

bash
$ cd

# 所有権を変更する
$ sudo chown -R solareenlo:solareenlo hello

$ cd hello

# Dockerfileを作成する
$ echo FROM vvakame/review > Dockerfile

# docker-compose.ymlを作成する
$ cat <<EOF > docker-compose.yml 
version: '3'
services:
  review:
    volumes:
      - .:/work
    build: .
    working_dir: /work
EOF

# pdfファイルを作成する
$ sudo docker-compose run review rake pdf

4. zathuraで作成したPDFを確認する

bash
$ sudo apt install zathura
$ zathura --fork book.pdf

5. いろいろ削除する

bash
# pdf作成過程で出来た不要なコンテナを削除する
$ sudo docker container prune

# Re:VIEWのDockerイメージを削除する
$ sudo docker image rm vvakame/review:latest

# zathuraを削除する
$ sudo apt uninstall zathura

あとは好きなエディタとドキュメントを見ながら作成する

参考文献

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