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

Failed to find Chrome binary について

前提

本日学んだことを書いていきます。
Docker
Ruby on Rails
Ruby

本題

Capybara でのテスト実行時に以下のようなエラーが出てしまい、ハマりました。。。

Failure/Error: visit login_path

          Webdrivers::BrowserNotFound:
            Failed to find Chrome binary.

Chrome binary が見つからない?
Chrome がないのが原因?
Docker環境内のためChromeが入っていないのかなと思いました。

解決方法

capybara.rb
#変更前
Capybara.register_driver :chrome_headless do |app|
  options = ::Selenium::WebDriver::Chrome::Options.new

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

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

Capybara.javascript_driver = :chrome_headless

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 :chrome_headless
  end
end
capybara.rb
#変更後
Capybara.register_driver :chrome_headless do |app|
  options = ::Selenium::WebDriver::Chrome::Options.new

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

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

Capybara.javascript_driver = :chrome_headless

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

  config.before(:each, type: :system, js: true) do
    if ENV["SELENIUM_DRIVER_URL"].present?
      driven_by :selenium, using: :chrome, options: {
        browser: :remote,
        url: ENV.fetch("SELENIUM_DRIVER_URL"),
        desired_capabilities: :chrome
      }
    else
      driven_by :selenium_chrome_headless
    end
  end
end
docker-compose.yml
#変更前
version: '3'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true
  db:
    image: mysql:5.7
    volumes:
      - db-volume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
volumes:
  db-volume:
docker-compose.yml
#変更後
version: '3'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true
    environment: #以下追記
    - "SELENIUM_DRIVER_URL=http://selenium_chrome:4444/wd/hub"
  selenium_chrome:
    image: selenium/standalone-chrome-debug
    logging:
      driver: none
  db:
    image: mysql:5.7
    volumes:
      - db-volume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
volumes:
  db-volume:

上記設定で解決しました。

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

Slackに代わるオンプレ型チャットツールRocket.Chatを導入する

Rocket.Chatとは?

オンプレへの導入が可能なSlackのようなチームコミュニケーションツールです。1
無料で使用できる上、自由度も高いため、Slackを何らかの理由で使えない企業にもってこいです。

なぜSlackを使わないの?

  • ファイルアップロード機能により、顧客情報が漏れることを懸念した。
  • 社外からでもSlackだとアクセスできてしまう(スマホなど)
  • Slackだとメッセージが無料枠で1万件までしか送信できない。

ここらへんの理由により、Rocket.Chatを導入することとなりました。

Rocket.Chat vs Slack

※Rocket.Chatはオンプレ版であるとします。

Rocket.Chat Slack
価格 無料 無料(有料あり)
環境 オンプレ クラウド
自由度 高い 価格次第
連携性 低い 高い
上司を説得 簡単 難しい

Rocket.Chatは設定や、権限周りが豊富で幅の広い設定が可能です。
Slackほどの他ツールとの連携力はありませんが、Hubotと連携しChatOpsな環境を作ることも可能です。2

導入

1.導入するディレクトリに以下のdocker-compose.ymlを配置

docker-compose.yml
version: '2'

services:
  rocketchat:
    image: rocket.chat:latest
    command: bash -c 'for i in `seq 1 30`; do node main.js && s=$$? && break || s=$$?; echo "Tried $$i times. Waiting 5 secs..."; sleep 5; done; (exit $$s)'
    restart: unless-stopped
    volumes:
      - ./uploads:/app/uploads
      - /etc/localtime:/etc/localtime:ro
    environment:
      - PORT=3000
      - ROOT_URL=http://xx.xx.xx.xx:3000
      - MONGO_URL=mongodb://mongo:27017/rocketchat
      - MONGO_OPLOG_URL=mongodb://mongo:27017/local
      - Accounts_UseDNSDomainCheck=false
      - TZ=Asia/Tokyo
    depends_on:
      - mongo
    ports:
      - 3000:3000

  mongo:
    image: mongo:4.0
    restart: unless-stopped
    volumes:
     - ./data/db:/data/db
     - ./data/dump:/dump
     - /etc/localtime:/etc/localtime:ro
    environment:
     - TZ=Asia/Tokyo
    ports:
     - 27017:27017
    command: mongod --smallfiles --oplogSize 128 --replSet rs0 --storageEngine=mmapv1

  mongo-init-replica:
    image: mongo
    command: 'bash -c "for i in `seq 1 30`; do mongo mongo/rocketchat --eval \"rs.initiate({ _id: ''rs0'', members: [ { _id: 0, host: ''localhost:27017'' } ]})\" && s=$$? && break || s=$$?; echo \"Tried $$i times. Waiting 5 secs...\"; sleep 5; done; (exit $$s)"'
    depends_on:
      - mongo

  hubot:
    image: rocketchat/hubot-rocketchat:latest
    restart: unless-stopped
    environment:
      - ROCKETCHAT_URL=xx.xx.xx.xx:3000
      - ROCKETCHAT_ROOM=GENERAL
      - ROCKETCHAT_USER=bot
      - ROCKETCHAT_PASSWORD=password
      - BOT_NAME=bot
      - RESPOND_TO_DM=true
      - RESPOND_TO_EDITED=true
      - HUBOT_ADAPTER=rocketchat
      - EXTERNAL_SCRIPTS=hubot-help,hubot-seen,hubot-links,hubot-diagnostics
      - TZ=Asia/Tokyo
    depends_on:
      - rocketchat
    volumes:
      - ./scripts:/home/hubot/scripts
      - /etc/localtime:/etc/localtime:ro
    labels:
      - "traefik.enable=false"
    ports:
      - 3001:8080

ROOT_URL=http://xx.xx.xx.xx:3000のxx部分は、
対象のホストのIPアドレスを持ってきてください。3

2.以下のコマンドを配置したディレクトリで実行

$ docker-compose up -d

プロキシに引っかかる場合

プロキシで引っかかる場合は、大体npmかDockerのプロキシ周りではないでしょうか。
以下のサイトが参考になるかと思います。

proxy環境でnpmを使う方法
日々プロキシで苦しむ人の為のプロキシ設定まとめ

最後に

Hubotを使いこなしたり、他のツールとの連携ができたら記事にしたいと思います。
よいRocket.Chatライフを!


  1. 公式GitHubです。 

  2. hubot-rocketchatはこちらから確認できます。 

  3. $ ip -4 aで取得できます。 

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

対処法 S3 InvalidAccessKeyId Rails Docker

現在、ポートフォリオを作成している途中のゆーた(@onoblog)です。
本番環境で、Rails carrierwave fog-awsでs3を実装中に、

<Error>
  <Code>InvalidAccessKeyId</Code>
  <Message>
    The AWS Access Key Id you provided does not exist in our records.
  </Message>
  <AWSAccessKeyId>古いアクセスキーID</AWSAccessKeyId>
.
.
.

S3 InvalidAccessKeyId エラーとなってしまいました。

原因特定に困り、解決までに、案外時間を取られたのでまとめておきます。

環境

  • rails 5.2.3
  • carrierwave
  • fog-aws
  • jquery-rails (4.3.5)
  • vue/cli 4.1.2
  • yarn 1.21.1
  • webpacker (5.0.1)
  • Docker 19.03.5
  • docker-compose 1.25.2
  • nginx 1.15.8

対処法

unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY

原因

最初は、awsのアクセスキーを間違って入力したと思っていました

しかし、私は、Rails credentials機能を使っているので、credentialsの中のawsのアクセスキーを書き換えて解決と思っていましたが、一向に治りませんでした。

理由は、以前設定したawsのアクセスキーの環境変数が読み込まれてしまっていたためでした。

echo $AWS_SECRET_ACCESS_KEY
echo $AWS_ACCESS_KEY_ID

上記のコードで、環境変数が残ってるか確認できます!

参考

https://stackoverflow.com/questions/39051477/the-aws-access-key-id-does-not-exist-in-our-records

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

Dockerイメージのなりすましや改ざんを防ぐには?(Docker Content Trust)

Dockerのイメージへのセキュリティ対策ってどうなっているのか、気になったので、調べてみました。

Dockerイメージのなりすましや改ざんを防ぐには?

Dockerイメージには、インフラ構成が含まれています。
なので、悪意のある第三者からの「なりすまし」や「改ざん」からイメージを保護する方が、外部からインフラ構成をみられることないため、安全です。
そこで、Docker Content Trustという機能を使うと、Dockerイメージの正統性を確認できます。

Docker Content Trust

Docker Content Trustの仕組み

公式サイト

署名

イメージ作成者がDockerレジストリにイメージをアップロードする前に、ローカル環境でイメージ作成者の秘密鍵を使ってイメージに署名します。
この秘密鍵のことをOffline Keyと呼ぶ。

この鍵があると、中身をみられてしまうので、しっかり管理します。

検証

署名されたイメージをダウンロードするときに、イメージ作成者の公開鍵を使って、イメージが本物かどうかを確認します。
もし改ざんされている場合は、そのイメージを無効化する。この公開鍵をTagging Keyを読みます。

Docker Content Trust機能を使う

以下のコマンドを実行し、設定する。

$ export DOCKER_CONTENT_TRUST=1

この機能を有効にすると、docker image pull コマンドを使ってイメージをダウンロードすると、イメージの検証が行われます。

署名がついていないイメージを使うとエラーになります。

Docker Content Trust無効化

DOCKER_CONTENT_TRUSTを0にするだけです。

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

Dockerコンテナ操作コマンドのまとめ

最近、dockerを勉強しています。
Dockerのコマンドって結構あって、覚えるの大変だなって思って、まとめました。

コンテナ生成/起動

$ docker container run [オプション] イメージ名[:タグ名] [引数]
オプション 説明
--attach, -a 標準入力/標準出力/標準エラー出力にアタッチ
--cidfile コンテナIDをファイルに出力する
--detach, -d コンテナを生成し、バッググラウンドで実行する
--interactive, -l コンテナの標準入力を開く
--tty, -t 端末デバイスを使う

コンテナを生成し、コンソールで対話的にコマンドを実行できます。

$ docker container run -it --name "test" centos /bin/bash

コンテナのバックグラウンド実行

$ docker container run [実行オプション] イメージ名[:タグ名] [引数]

オプション「-d」をつけると、バックグラウンド実行できる。

オプション 説明
--detach, -d コンテナを生成し、バッググラウンドで実行する
--user, -u ユーザー名を指定
--restart=[リスタート条件] コマンドの実行結果によって再起動を行う
--rm コマンド実行完了後にコンテナを自動で削除

リスタート条件

設定値 説明
no 再起動しない
on-failure 終了ステータスが0でない時に再起動する
on-failure:回数n 終了ステータスが0でない時にn回再起動する
always 常に再起動する
unless-stopped 直近のコンテナが停止状態でなければ、常に再起動する
$ docker container run -d centos /bin/ping localhost

コンテナを生成をし、localhostに対してpingコマンドを実行しています。
バックグラウンドで実行することをデタッチモードと呼びます。

対話式では、コマンドの結果がコンソール上に表示されるが、バックグラウンドでは起動したコンテナのコンテナIDが表示される。

バッググラウンドで実行されているかの確認

$ docker container logs

コンテナのネットワーク設定

$ docker container run [ネットワークオプション] イメージ名[:タグ名] [引数]
オプション 説明
--add-host=[ホスト名:IPアドレス] コンテナの/etc/hostsにホスト名とIPアドレスを定義する
--dns=[IPアドレス] コンテナ用のDNSサーバのIPアドレス指定
--expose=[IPアドレス] 指定したレンジのポート番号を割り当てる
--mac-address=[MACアドレス] コンテナのMACアドレスを指定する
--net=[ネットワーク名] コンテナのネットワークを指定する
--hostname, -h コンテナ自身のホスト名を指定する
--publish, -p[ホストのポート番号]:[コンテナのポート番号] ホストとコンテナのポートマッピング
--publish-all, -P ホストの任意のポートをコンテナに割り当てる

netオプションで指定する値

設定値 説明
brige ブリッジ接続を使う
none ネットワークに接続しない
containe:[name id]
host コンテナがホストOSのネットワークを使う
NETWORK ユーザー定義ネットワークを使う

ポートマッピング

$ docker container run -d -p 8080:80 nginx

ホストの8080ポートにアクセスすると、コンテナ上で動作するNginx(80番ポート)のサービスにアクセスできます。

DNSサーバを設定する

$ docker container run -d --dns IPアドレス nginx

などなど設定ができます。

リソースを指定してコンテナを生成/実行

$ docker container run [リソースオプション] イメージ名[:タグ名] [引数]
オプション 説明
--cpu-shares,-c CPUの使用の配分(比率)
--memory, -m 使用するメモリを制御して実行する
--volume=[ホストのディレクトリ]:[コンテナのディレクトリ], -v ホストとコンテナのディレクトを共有

コンテナを起動する時CPUとメモリのリソース利用を制限することができます。

デフォルトのcpu-sharesは、1024です。

コンテナの生成/起動する環境を指定

$ docker container run [環境設定オプション] イメージ名[:タグ名] [引数]
オプション 説明
--env, -e 環境変数を設定する
--env-file=[ファイル名] 環境変数をファイルから設定する
--read-only=[true or false] コンテナのファイルシステムを読み込み専用にする
--workdir=[パス],-w コンテナの作業ディレクトリを指定する
--user=[ユーザー名],-u ユーザー名またはUIDを設定する

稼働コンテナの一覧表示

$ docker container ls [オプション]
オプション 説明
--env, -e 環境変数を設定する
--env-file=[ファイル名] 環境変数をファイルから設定する
--read-only=[true or false] コンテナのファイルシステムを読み込み専用にする
--workdir=[パス],-w コンテナの作業ディレクトリを指定する
--user=[ユーザー名],-u ユーザー名またはUIDを設定する

--formatオプションを指定して、出力形式を変更することも可能。

コンテナの稼働確認

$ docker container stats [コンテナ識別子]

コンテナの起動

$ docker container start [コンテナ識別子]
オプション 説明
--attach, -a 標準出力/標準エラー出力を開く
--interactive, -l コンテナの標準入力を開く

コンテナの停止

$ docker container stop [オプション] コンテナ識別子 [コンテナ識別子]
オプション 説明
--time, -t コンテナの停止時間を指定する

コンテナの再起動

$ docker container restart [オプション] コンテナ識別子 [コンテナ識別子]
オプション 説明
--time, -t コンテナの停止時間を指定する

コンテナの削除

$ docker container rm [オプション] コンテナ識別子 [コンテナ識別子]
オプション 説明
--force, -f 起動中のコンテナを強制的に削除する
--valumes, -v 割り当てたボリューム削除

コンテナの中断/再開

中断

$ docker container pause コンテナ識別子

再開

$ docker container uppause コンテナ識別子
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Zabbixエージェント2を使用したDockerの監視

はじめに

Zabbix 5.0で正式にサポートとなったZabbixエージェント2(Zabbix agent 2)ですが、プラグインとしてOS関連以外に以下のようなものに対する監視のための機能が用意されています。

  • Docker
  • Memcached
  • MySQL
  • Redis

その中でも今回はDockerの監視の設定を紹介します。

Docker環境の準備

この資料では、Docker CE(Community Edition)の監視をご紹介します。

公式には、CentOS 8上ではDocker CEのサポートはされておらず、CentOS 8上でDocker互換のコンテナを稼働させるには、Podmanというソフトウェアを使用することになっています。このPodmanは、root権限でのデーモンやroot権限を必要とするような実行環境ではないので、セキュリティを考慮したものとなっているようです。(他にもいろいろ考慮されているようです。)

しかし、今回紹介しようとしているZabbixエージェント2のDocker用プラグインでは、Dockerのソケットを使用してメトリクスを取得するものとなっているので、Podmanの環境では現時点では機能しないと思われます。そこで今回は、Docker CEを用いたものとします。

CentOS 8上にDocker CEのインストール

公式にサポートされてはいませんが、インターネット上で公開されていた情報を整理した手順は以下のようになります。
バージョンによっては手順が異なる場合があるかもしれませんが、紹介する手順は以下のバージョンの組み合わせです。

  • CentOS 8.1.1911
  • docker-ce-19.03.9-3 (最終的なアップデート実行後)

それでは実際の手順です。

# dnf remove podman
# dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# dnf install --nobest docker-ce docker-ce-cli
# dnf update https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.1.el7.x86_64.rpm
# dnf update
# systemctl start docker
# systemctl enable docker
# firewall-cmd --add-masquerade --permanent
# firewall-cmd --reload

最初にpodmanというパッケージを削除しているのは、上で紹介したPodmanが既にインストールされていた場合用の手順です。
そして、Docker用のリポジトリを登録して、そのリポジトリからdocker-ceをインストールするわけです。その後にRHEL 7用パッケージで一時的にcontainerd.ioだけを無理やりアップデートするのは、その後に、dnfコマンドでアップデートできるようにするためです。

firewalldの設定は、Docker HUBなどからイメージを取得するために、上記のような設定をしてみました。

Zabbixエージェント2のインストール

CeneOS 8へのZabbixエージェント2のインストール

Zabbix公式のリポジトリを使用してインストールします。

# dnf install https://repo.zabbix.com/zabbix/5.0/rhel/8/x86_64/zabbix-release-5.0-1.el8.noarch.rpm
# dnf install zabbix-agent2
# vi /etc/zabbix/zabbix_agent2.conf
# firewall-cmd --add-port=10050/tcp --zone=public --permanent
# firewall-cmd --reload
# gpasswd -a zabbix docker
# systemctl start zabbix-agent2
# systemctl enable zabbix-agent2

設定ファイルが、/etc/zabbix/zabbix_agent2.confになっている点に注意が必要ですが、基本的な設定は従来のZabbixエージェントと同様に、Hostname、Server、ServerActiveなどを設定してください。

Zabbixサーバー上での監視設定の追加

ZabbixサーバーからLinuxのOS部分とDockerの両方を監視するのであれば、その対象のホストに以下の2つのテンプレートをリンクさせます。

  • Template OS Linux by Zabbix agent
  • Template App Docker

今回紹介しているZabbixエージェント2のDockerの監視機能では、Dockerのソケットインターフェースを使用してメトリクスを取得しています。CentOS 8上にDocker CEをインストールした場合は、「/var/run/docker.sock」がそのソケットです。

デフォルトでは以下のようなパーミッションになっていると思います。

# ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0  4月  1 18:16 /var/run/docker.sock
#

つまり、rootユーザーか、dockerグループのユーザーのみが読み書きのアクセスすることができるようになっています。
Zabbixエージェント2がアクセスできるようにするには、Zabbixエージェント2を起動しているユーザー「zabbix」でこのソケットにアクセスすることが必要であるため、いくつか方法はあると思いますが、ユーザー「zabbix」をdockerグループに所属させる方法を取ることを選択してみました。先ほどの手順内にあった

# gpasswd -a zabbix docker

を実行していたのはそのための手順です。

監視できる主な項目

Docker環境全体としては、以下のようなメトリクスを取得できます。

  • Dockerのバージョン
  • ホストOSやカーネルのバージョン
  • ホストのアーキテクチャとCPU数、積載メモリ
  • 使用しているストレージドライバ
  • 有効なイメージの数やサイズ

コンテナごとには以下のようなメトリクスを取得できます。

  • 作成日時
  • CPU使用量(kernel、usermode)
  • メモリ使用量
  • ネットワークI/O
  • ベースイメージ

ダウンロード済みのイメージごとに関しては以下のようなメトリクスを取得できます。

  • 作成日時
  • サイズ

最後に

UbuntuなどCentOS 8以外に関しても後で追記しようと思います。

参考URL

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

丁寧にNginx + MySql + Rails6 (Using Webpacker) on Dockerな開発環境を構築します。

Nginx + MySql + Rails6 (Using Webpacker) on Dockerな開発環境を構築します。
新しくプロジェクトから作成する機会なんてそうそうないので、以下手順をできるだけ要点を抑えつつまとめました。

今回しないこと。

プロジェクトの立ち上げにコミットするために以下についてはしない。

  • 実際のコーディングはしない。1
  • RSpec, Rubocopのようなコードの品質を上げるための設定はしない。
  • 開発効率を上げるためのgem登録などは設定しない。
  • i18nのような初期に設定するようなものも今回は設定しない。

asset pipelineの代わりにWebpackerを使用しています。なので、Webpackerについてはこの辺をざっと見ておくとよいです。

各バージョンについて

name version
Ruby(on docker) 2.6.5
Ruby on Rails 6.0.3
node 10.19.0
yarn 1.22.4
bundler 2.1.4
webpacker 5.1
docker 19.03.8
docker-compose 1.25.5
MySQL(on docker) 5.7
nginx(on docker) 1.17.3

※ (on docker)は、Dockerfileで指定しているバージョンです。

Rails6ではyarnを利用するので、事前にインストールしておく。

brew install yarn

1. プロジェクト構築手順

1-1. Githubにプロジェクトを作成し、git cloneしておく。

# githubでプロジェクトを作成しておく。
$ git clone git@github.com:{github_acount}/{project_name}.git
$ cd {project_name}

1-2. ruby,nodeのバージョンを指定する。

rubyとnodeのバージョンをしているするために.*-versionファイルを作成します。
※ anyenvを事前にbrew install anyenvしておくとよい。

また、rbenv, nodenvの設定については公式を参考にするとよい。

- 参考:GitHub - anyenv/anyenv: All in one for **env

1-2-1. Rubyバージョン指定

ruby : 2.6.5を指定

# インストールできるバージョンをの一覧を確認する。
$ rbenv install -l 
$ rbenv install 2.6.5
$ rbenv local 2.6.5
$ ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin18]

1-2-2. Nodeバージョン指定

node : v10.19.0を指定

# インストールできるバージョンをの一覧を確認する。
$ nodenv install -l
$ nodenv install 10.19.0
$ nodenv local 10.19.0
$ node -v
v10.19.0

1-3 不要なファイルをコミットできないように.gitignoreを作成する。

.gitignoreを作成し、git commitしておく。
※ .gitignoreを作成するために事前にbrew install giboしておくとよい。

# .gitignoreを作成
$ gibo dump macOS Node Ruby Rails VisualStudioCode > .gitignore

1-4. GemfileとGemfile.lockを作成する。

$ gem install bundler
Successfully installed bundler-2.1.4
Parsing documentation for bundler-2.1.4
Done installing documentation for bundler after 1 seconds
1 gem installed

次に、Gemfileを作成する。

# Gemfileを作成する。
$ bundle init

Gemfileファイルを開きrailsのgemを登録します。
バージョンについてはrails | RubyGems.orgを確認する。

  • ./Gemfile
# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

- # gem "rails"
+ gem 'rails', '~> 6.0', '>= 6.0.3'

bundle installを実行しGemfile.lockファイルを作成します。

$ bundle install
Fetching gem metadata from https://rubygems.org/.............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using rake 13.0.1
Using concurrent-ruby 1.1.6
...
Using rails 6.0.3
Bundle complete! 1 Gemfile dependency, 43 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

Ruby on Railsプロジェクトを作成するための準備が完了しました。

2. Ruby on Railsアプリケーションを構築する。

Ruby on Railsのアプリケーションを作る。

$ bundle exec rails new . --database=mysql --skip-git --skip-test-unit --skip-sprockets

...
├─ webpack-dev-server@3.11.0
└─ ws@6.2.1
✨  Done in 3.19s.
Webpacker successfully installed
オプション 説明
. カレントディレクトリ名がプロジェクト名
--database=mysql databaseはmysql
--skip-git .gitignoreを組み込まない(事前に作成済み)
--skip-test-uni Test::Unitを組み込まない
--skip-sprockets sprocketsを利用しない

2-1 Ruby on Railsの設定する。

2-1-1 webpackerのバージョンを最新にする。

  • ./Gemfile
- gem 'webpacker', '~> 4.0'
+ gem 'webpacker', '~> 5.1', '>= 5.1.1'

2-1-2 MySQLを利用するためにdocker-composeを用意する。

# mysqlのDockerfileとmy.cnfを用意する。
# docker-compose.ymlを用意する。
$ mkdir -p ./docker/mysql
$ touch ./docker/mysql/{Dockerfile, my.cnf}
$ touch ./docker-compose.yml

各ファイルの記述はこちら。

  • ./docker/mysql/Dockerfile
FROM mysql:5.7

RUN touch /var/log/mysql/mysqld.log
  • ./docker/mysql/my.cnf
[mysqld]
collation-server=utf8mb4_general_ci
character-set-server=utf8mb4
skip-character-set-client-handshake
init-connect = SET NAMES utf8mb4
default-time-zone=+9:00
explicit-defaults-for-timestamp=1
general-log-file=/var/log/mysql/mysqld.log

[client]
default-character-set=utf8mb4
  • ./docker-compose.yml
version: '3.3'
services:
  database:
    build:
      context: .
      dockerfile: ./docker/mysql/Dockerfile
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: {project_name}_development
    ports:
      - "3306:3306"
    volumes:
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./log/mysql:/var/log/mysql

mysqlアカウントでrootを利用する場合は、MYSQL_ROOT_PASSWORDを設定するだけでよい。
MYSQL_DATABASEは開発で利用するデータベース名にする。

2-1-3 Ruby on Railsのdatabase.ymlを修正する。

database.ymlを修正してrailsからmysql on dockerに接続できるようにする。

  • ./config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_general_ci
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: 127.0.0.1

development:
  <<: *default
  database: {project_name}_development

logを取得するために2

# Nginx用のlog吐き出し用
$ mkdir ./log/mysql
$ touch ./log/mysql/mysqld.log

2-1-4 Ruby on Railsのディレクトリ構成を修正する。

Webpackerを利用してJS,CSS,Image等を扱うための構成にします。

$ mkdir -p ./app/javascript/{stylesheets, images}
$ touch ./app/javascript/stylesheets/application.scss

2-1-5 [S]CSSファイル、ImageをWebpackerで扱う

  • ./app/javascript/packs/application.js
- // const images = require.context('../images', true)
- // const imagePath = (name) => images(name, true)
+ const images = require.context('../images', true)
+ const imagePath = (name) => images(name, true)
+ import "../stylesheets/application";

2-1-6 stylesheet_pack_tagに切り替える。

  • ./app/views/layouts/application.html.erb
-    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
+    <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>

2-1-7 check_yarn_integrityの設定をfalseにする。

  • config/webpacker.yml
development:
  <<: *default
  compile: true

  # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
-  check_yarn_integrity: true
+  check_yarn_integrity: false

2-1-8 extract_css: false -> trueにする。

開発中でもCSSファイルを作成してほしいのでextract_cssをtrueにします。

- config/webpacker.yml

# Extract and emit a css file
- extract_css: false
+ extract_css: true

2-1-8 assetsを生成しないようにする

  • ./config/initializers/generators.rb
Rails.application.config.generators do |g|
  g.assets false
  g.test_framework false
end

2-2 MySQL on Dockerを起動する。

# mysqlを起動する。
$ docker-compose -d up database

mysqlを起動したらmysqlの照合順序を確認する。

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

2-3 ローカルPCからRuby on Railsを起動する。

# railsを起動する。
$ bin/rails s --port=3000 -b 0.0.0.0

以下の画面が表示されればOK。



3. Ruby on Rails on Dockerを構築する。

3-1. Dockerfileを作成する。

  • ./Dockerfile
FROM ruby:2.6.5

RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install -y \
    build-essential \
    nodejs \
    yarn \
    default-mysql-client \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

ENV LANG ja_JP.UTF-8

RUN mkdir -p /app
WORKDIR /app

COPY Gemfile Gemfile.lock ./

RUN gem update bundler && bundle install

COPY . .

RUN yarn install --check-files
RUN yarn webpack --config ./config/webpack/development.js

CMD ["rails", "server", "-b", "0.0.0.0"]

3-2. docker-compose.ymlにapp:を追加する。

environmentで環境変数[RAILS_HOST]にdatabaseを指定します。
- ./docker-compose.yml

version: '3.3'
services:
+  app:
+    build: .
+    command: bundle exec rails s -b 0.0.0.0
+    volumes:
+      - .:/app:cached
+    ports:
+      - 3000:3000
+    depends_on:
+      - database
+    tty: true
+    stdin_open: true
+    environment:
+      RAILS_HOST: database
  database:
    build:
      context: .
      dockerfile: ./docker/mysql/Dockerfile
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: nginx_rails_with_webpacker_mysql_on_docker_development
    ports:
      - "3306:3306"
    volumes:
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./log/mysql:/var/log/mysql

docker-composeで立ち上げる場合は環境変数hostを指定し、ローカル上で起動する場合は127.0.0.1を指定する。

  • config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
- host: 127.0.0.1
+ host: <%= ENV.fetch("RAILS_HOST") { '127.0.0.1' } %>

3-3. Ruby on Rails on Dockerを起動する。

# Ruby on Rails + MySQL on Dockerで起動する。
$ docker-compose up -d --build

ブラウザでhttp://localhost:3000にアクセスします。

改めて、Yay! You’re on Rails!の画面が表示されればOK.

4. nginx on Dockerを用意する。

Nginx(webサーバー)を用意します。

Nginx用のDockerfileとnginx.confを用意します。

# nginx用のファイルを作成する。
$ mkdir -p ./docker/nginx
$ touch ./docker/nginx/{Dockerfile, nginx.conf}

各ファイルの記述はこちら。

  • ./docker/nginx/Dockerfile
FROM nginx:1.17.3

RUN mkdir -p /usr/share/nginx/public

COPY ./docker/nginx/nginx.conf /etc/nginx/conf.d/default.conf
CMD ["nginx", "-g", "daemon off;"]
  • ./docker/nginx/nginx.conf
server {
  listen       80;
  server_name  web;
  root /usr/share/nginx/public;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  location @app {
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_pass http://app:3000;
  }

  location / {
      try_files $uri @app;
  }

  location ~ ^/(assets|packs)/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  location = /favicon.ico { access_log off; log_not_found off; }
  location = /robots.txt  { access_log off; log_not_found off; }

  location ~ /\.(?!well-known).* {
    deny all;
  }
}

logを取得するために

# Nginx用のlog吐き出し用
$ mkdir ./log/nginx
$ touch ./log/nginx/{access.log, error.log}

docker-compose up --buildを実行します。

ブラウザでhttp://localhostにアクセスします。
改めて、Yay! You’re on Rails!の画面が表示されればOK.

5. プロジェクトをちょっとだけカスタマイズ

こちらは、やったほうがいいと思われるが任意なあれこれです。

5-1. Add SplitChunks (Webpack V4)

SplitChunksPluginとは、共通で使用するpackageのJavaScriptファイルを纏める機能のことです。
デフォルトの設定を例としてあげておきます。チューニングする場合は公式を確認する。

  • ./config/webpack/environment.js
const { environment } = require('@rails/webpacker')
+ environment.splitChunks()

module.exports = environment

splitChunksを利用する場合は、JavaScriptファイルを読み込むヘルパーメソッドはjavascript_packs_with_chunks_tagになる。

- <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
+ <%= javascript_packs_with_chunks_tag 'application', 'data-turbolinks-track': 'reload' %>

5-2. app/assetsを削除する。

でも、app/assets/config/manifest.jsがないと怒らせる。

Expected to find a manifest file in `app/assets/config/manifest.js` (Sprockets::Railtie::ManifestNeededError)

プロジェクト作成時に-–skip-sprocketsを実行してもsprocketsのgemはインストールされプロジェクト内部ではまだ利用しているようです。そのため、app/assets配下のManifestファイルを削除してしまうとSprockets::Railtie::ManifestNeededErrorが発生します。

対策としては、Gemfileにgem 'sprockets', '< 4'を追加し、bundle update sprocketsすると良いようです。(2020/05時点)

$ bundle update sprockets
Using sprockets 3.7.2 (was 4.0.0)

5-3. app/javascriptをapp/frontendにする。

app/javascriptからapp/frontendに変更するという記事が多いように感じます。

./config/webpacker.ymlでsource_entry_pathを指定できるのでお好みで。

  • ./config/webpacker.yml
default: &default
- source_path: app/javascript
+ source_path: app/frontend
  source_entry_path: packs
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/webpacker
  check_yarn_integrity: false
  webpack_compile_output: true

5-4. ブラウザにlocalhostとか127.0.0.1とか0.0.0.0と入れるのはちょっと。

sudo vi /etc/hostsを実行し、HOST DATABASEにお好みのドメイン名を追加する。

保存してブラウザでdev-application.localhostと入力してみよう。

127.0.0.1       dev-application.localhost

5-5. docker-compose upで、A server is already running. Check /app/tmp/pids/server.pid.と言われて起動できない。

今回環境構築するために何度かdocker-compose upを実行しました。その時に当該事象が発生しました。
これはdocker-composeのバグないそうですが、よく起きている事象のようです。
対策は、調べた限りですが2つあります。4

5-5-1. 対処方法 1

docker-compose.ymlのcommandでbundle exec rails s..の前に削除コマンドを仕込む方法です。

command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"

5-5-1. 対処方法 2

DockerのCMDにスクリプトを登録しておく。
対応していることはtmp/pids/server.pidを削除するということは一緒ですが、スクリプトにすることで実行時に事前に行いたい処理を追加していくことができます。ワンライナーなスクリプトよりも見通しがいいのでこちらもおすすめです。

# Docker
CMD [foreground]
# foreground.sh
#!/bin/bash
set -e

rm -f tmp/pids/server.pid

bin/rails s -b 0.0.0.0 -p 3000

5-6. webpack-dev-server on Dockerを用意する。

webpack-dev-serverをDockerで構築します。5
Dockerで構築するほうがいい理由についてはまだ腹落ちしていないため任意

# ./docker-compose.yml
version: '3.3'
services:
  web:
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    volumes:
      - ./public:/usr/share/nginx/public:cached
      - ./log/nginx:/var/log/nginx
    ports:
      - 80:80
    depends_on:
      - app
  app:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app:cached
    ports:
      - 3000:3000
    depends_on:
      - database
    tty: true
    stdin_open: true
    environment:
      RAILS_HOST: database
+     WEBPACKER_DEV_SERVER_HOST: webpacker
+ webpacker:
+   build: .
+   command: ./bin/webpack-dev-server
+   volumes:
+     - .:/webpacker-example-app
+   ports:
+     - '3035:3035'
+   tty: true
+   stdin_open: true
+   environment:
+     - NODE_ENV=development
+     - RAILS_ENV=development
+     - WEBPACKER_DEV_SERVER_HOST=0.0.0.0
+   depends_on:
+     - app
  database:
    build:
      context: .
      dockerfile: ./docker/mysql/Dockerfile
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: nginx_rails_with_webpacker_mysql_on_docker_development
    ports:
      - "3306:3306"
    volumes:
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./log/mysql:/var/log/mysql
  • ./docker/nginx/nginx.conf
server {
  listen       80;
  server_name  web;
  root /usr/share/nginx/public;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;


  location @app {
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_pass http://app:3000;
  }

  location / {
      try_files $uri @app;
  }

  location ~ ^/(assets|packs)/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;`v
  }

  location = /favicon.ico { access_log off; log_not_found off; }
  location = /robots.txt  { access_log off; log_not_found off; }

+  # Proxy webpack dev server websocket requests
+  location /sockjs-node {
+      proxy_redirect off;
+      proxy_http_version 1.1;
+      proxy_set_header Upgrade $http_upgrade;
+      proxy_set_header Connection "upgrade";
+      proxy_pass http://127.0.0.1:3035; # change to match your +webpack-dev-server host
+  }

  location ~ /\.(?!well-known).* {
    deny all;
  }
}

docker-compose up --buildを実行します。

ブラウザでhttp://localhostにアクセスします。
改めて、Yay! You’re on Rails!の画面が表示されればOK.

まとめ

  • rails/webpackarには情報がちゃんと記載されている。(webpacker/doc)
  • webpackerはおすすめしないという記事もあるが、みなさん共通して利用するならちゃんと考えましょう。とおっしゃっているのでちゃんと考えるために一度導入してみて感触を掴んだほうがいい。(逆に導入しない方法も構築してみるといいと思う。)
  • 開発環境のセットアップだけでも時間が掛かる。しかし、はじめにいろいろ検討しておくと開発がしやすくなる。
  • それぞれの設定についてもなぜ、そうしたのか。をまとめておけると後から再検討や情報共有する時に役に立つ。
  • rails6のセットアップと注意点を一通り学習することができた。
  • 実際は、rails new のタイミングで react や veuの利用を選択することがあると思うのでそこは適宜この手順と照らし合わせながら進めればいいと思う。

  1. ただ、scaffoldぐらいは実施しています。載せていないだけ。 

  2. 設定はしましたが、ログが吐き出されたかは未確認だったりします。。 

  3. location ~ /\.(?!well-known).*についてはもう少し学習しないと... 

  4. /app/tmp/pids/server.pid.については、対処方法1を採用しました。 

  5. この方法でうまくwebpack-dev-serverが動いているかはまだ、未確認です。 

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

【Laravel】 ネストしたEagerLoadを書いてみる

やりたいこと

以下のテーブル構成があったときに、
マンションテーブルの情報から郵便番号テーブルの住所名を取得したいときに、
ネストしたEagerLoadを使用することができたので、残します。

マンションテーブル(apartments)

項目名 カラム名 外部キー
id マンションID

マンションの基本情報テーブル(apartment_infos)

項目名 カラム名 外部キー
id マンションの基本情報のID
apartment_id マンションテーブルのID apartments.id
postal_code 郵便番号 postal_codes.postal_code

郵便番号テーブル(postal_codes)

項目名 カラム名 外部キー
postal_code 郵便番号
name 住所名(愛媛県松山市...)

公式の説明

Laravel 5.4 Eloquent:リレーション

初歩の初歩なのか、あっさりと書かれていて、
私はぱっと見ただけでは理解出来ませんでした。

実際のコード

モデル
//マンションモデル
class Apartment extends Model{
    public function apartmentInfo()
    {
        //マンションの基本情報テーブルとの関係を明示
        return $this->hasOne(ApartmentInfo::class,"id" , "id")->withDefault();
    }
}

//マンションの基本情報モデル
class ApartmentInfo extends Model{
    public function postalCode()
    {
        //郵便番号テーブルとの関係を明示
        return $this->hasOne(PostalCode::class,"postal_code" , "postal_code")->withDefault();
    }
}

//郵便番号のモデル
class PostalCode extends Model{
}

コントローラ
    public function sample(){
        $apartments = Apartment::with(
            ["apartmentInfo", "apartmentInfo.postalCode"])->get();

        var_dump($apartments->ApartmentInfo->PostalCode->name);
    }

感想

最初は、郵便番号のモデルに、findするようなメソッドを用意していたが、
N+1クエリ問題が発生してしまうので、どうにかならないかなあと思っていたところ、改善できてよかった。

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

【調査中】DockerでGUIアプリを起動する(amd64)(NVIDIA)

やりたいこと

amd64のGPU付きノートPCで、Docker上でROS/ROS2を起動して、rvizやgazeboを動かしたい。
本体環境を保護して、別のマシンに環境をそのまま持っていくことが目的。
やり方が理解できないので、先人のやっていることを理解しながらのメモ。

やりたいことをもう少し細分化

  • GPU付きのノートPCのDocker環境でROSを動かす
  • GUIが画面に出力されるようにする
  • ディレクトリをホストと共有したい

参考にしている情報

シンプルに書いてある。参考になりそう。
DockerでGUIアプリを実行する

OpenGLが動くDockerイメージ
nvidia/opengl

CUDAとOpenGLが動くDockerイメージ
nvidia/cudagl

やりたいことは、この方と同じこと。
ROSをdocker上で動かすサンプル.rvizなどのGUIアプリケーションも動作するはず.

ROS.org 公式の説明
Using GUI's with Docker

個人的に常々参考にさせていただいている。ARMコア用
NVIDIA JetsonデバイスでROSを起動するDockerfile

gazeboバイナリを取得するDockerfileの書き方が大変参考になりそう
ROS / GAZEBOでのPriusのデモ

WEBブラウザ経由で試せるROS/ROS2環境。私も使ってます。
ROS/ROS2のGUIをWebブラウザ経由でお手軽に試せるDockerfileを公開しました

条件

CORE i7 GTX1660TiのノートPCで、ホストOSはUbuntu18.04
Docker19.xで実施する。
NVIDIA-dockerは使用しない。

試してみること

  • GPUなしでGUIを起動し、FireFoxなど立ち上げてみる
  • GPUなしでOpenGLアプリを起動する
  • GPUありでGUIを起動し、FireFoxなど立ち上げてみる
  • GPUありでOpenGLアプリを起動する

色々ためしてみる

ネット上のサンプルを元に、実施可能かどうかやってみることにします。

1.ROSをdocker上で動かすサンプル(NG)

まずはこちらを参考に、rvizが立ち上がるかやってみます。

ROSをdocker上で動かすサンプル.rvizなどのGUIアプリケーションも動作するはず.

docker_build
$ docker build --tag shinsumicco/ros:kinetic-desktop-standard --file Dockerfile.kinetic.standard .
$ docker network create rosnet

ターミナルを2つ開いて実行

terminal1
$ cd /path/to/docker-ros/
$ ./run.kinetic.standard --name roscore --net rosnet
# sudo chown -R $USER:$USER .
# roscore
... logging to /home/kuma/.ros/log/e940edd6-9dfa-11ea-ba03-0242ac120002/roslaunch-c2169f1a0bde-33.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://c2169f1a0bde:40163/
ros_comm version 1.12.14


SUMMARY
========

PARAMETERS
 * /rosdistro: kinetic
 * /rosversion: 1.12.14

NODES

auto-starting new master
process[master]: started with pid [43]
ROS_MASTER_URI=http://c2169f1a0bde:11311/

setting /run_id to e940edd6-9dfa-11ea-ba03-0242ac120002
process[rosout-1]: started with pid [56]
started core service [/rosout]

roscoreの実行で表示されるURLをターミナル2の起動引数にする。

terminal2
$ ./run.kinetic.standard --name rviz --net rosnet --env ROS_HOSTNAME=rviz --env ROS_MASTER_URI=roscoreの起動URLを使う
# sudo chown -R $USER:$USER .
# rosrun rviz rviz

[ INFO] [1590351256.773212816]: rviz version 1.12.17
[ INFO] [1590351256.773241018]: compiled against Qt version 5.5.1
[ INFO] [1590351256.773249629]: compiled against OGRE version 1.9.0 (Ghadamon)
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
Could not initialize OpenGL for RasterGLSurface, reverting to RasterSurface.
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
Segmentation fault (core dumped)

OpenGLのライブラリのエラーが表示されて、異常終了してしまいました。
GPU付きのPCだとうまく行かないのかな?

もう片方のGPU用はNVIDIA-Dockerを使用するということでやめておくことにします。

2.X11ソケットをコンテナーと共有して直接使用する(OK)

DockerでGUIアプリを実行する

こちらを試してみます。

FROM ubuntu:14.04

RUN apt-get update && apt-get install -y firefox

# Replace 1000 with your user / group id
RUN export uid=1000 gid=1000 && \
    mkdir -p /home/developer && \
    echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \
    echo "developer:x:${uid}:" >> /etc/group && \
    echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \
    chmod 0440 /etc/sudoers.d/developer && \
    chown ${uid}:${gid} -R /home/developer

USER developer
ENV HOME /home/developer
CMD /usr/bin/firefox

Dockerfileをビルドして実行します。

terminal
$ docker build -t firefox .
$ docker run -ti --rm \
       -e DISPLAY=$DISPLAY \
       -v /tmp/.X11-unix:/tmp/.X11-unix \
       firefox

これはあっさり動作しました。
X11の設定が妥当になされていれば、実施できるようです。

Screenshot from 2020-05-25 05-58-14.png

3.CUDAとOpenGLが動くコンテナを作り、画面に表示してみる

CUDA10.2+OpenGL(glvnd1.0) をpullしてみます。
タグはbase/runtime/develの3種類がありますが、どういう区分かわからないので、baseを選びます。(dockerhubに説明書いてほしい)

terminal
$ docker pull nvidia/cudagl:10.2-base-ubuntu18.04
$ docker run -it --rm -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY --name glvnd nvidia/cudagl:10.2-base-ubuntu18.04

テストのため、Dockerコンテナの中で、xeyesをインストールして実行してみます。

terminal
# apt-get install x11-apps:i386
# xeyes
No protocol specified
Error: Can't open display: :0

あら?開かない。

X11でうまく行ったDockerfileをそのまま使う。
完全にそのままだと、「/bin/sh: 1: cannot create /etc/sudoers.d/openwrt: Directory nonexistent」が発生する。
sudoがインストールされていないので、sudoをインストールするように修正すると動作する。

sudoを追加
FROM nvidia/cudagl:10.2-base-ubuntu18.04

RUN apt-get update && apt-get install -y firefox sudo

# Replace 1000 with your user / group id
RUN export uid=1000 gid=1000 && \
    mkdir -p /home/developer && \
    echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \
    echo "developer:x:${uid}:" >> /etc/group && \
    echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \
    chmod 0440 /etc/sudoers.d/developer && \
    chown ${uid}:${gid} -R /home/developer

USER developer
ENV HOME /home/developer
CMD /usr/bin/firefox

実行はこちら

terminal
$ docker run -it --rm -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY --name glvnd cuda_gui

これで、FirefoxはDockerのなかからGUIで表示されました。

CUDAのバージョンをnvidia-smiで確認してみる

FireFoxを立ち上げたときはGPUが有向になっていませんでした。
--gpus all を引数に追加してみます。
FireFoxの起動の代わりにbashを起動して挙動を試します。

terminal
$ docker run -it --gpus all --rm -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY --name glvnd cuda_gui
$ nvidia-smi 

Tue May 26 09:37:22 2020       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.82       Driver Version: 440.82       CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 166...  Off  | 00000000:01:00.0 Off |                  N/A |
| N/A   45C    P8     6W /  N/A |    458MiB /  5944MiB |      5%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

nvidia-smi を実行して、GPUが認識されていることが確認できました。
CUDA10.2もインストールされているようです。

OpenGLのベンチマークソフトを実行させてみる

適当なベンチマークソフトをコンテナにインストールして実行します。

$ sudo apt-get install glmark2
$ glmark2

このように、デスクトップにGUIが表示されました。

Screenshot from 2020-05-26 18-47-24.png

できたコンテナに、ROSなどを追加してみる

(続きを編集中)

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

goose設定ファイルに環境変数を読み込めない(Docker環境)

概要

Docker環境でGo製マイグレーションツールのgooseを使用する際、設定ファイルであるdbconf.ymlが環境変数を読んでくれませんでした。

dbconf.yml

development:
  driver: mymysql
  open: $MYSQL_URI

環境変数は、$変数という形式で読み込んでくれるはずなのですが・・・(公式参照)

Dockerfile

FROM golang:1.14.2-alpine

WORKDIR /go/src/server
COPY . .
ENV GO111MODULE=on

RUN apk add --no-cache \
        alpine-sdk=1.0-r0 \
    && go get github.com/pilu/fresh \
              bitbucket.org/liamstask/goose/cmd/goose
CMD ["fresh"]

コンテナ内でgooseコマンドを使うため、コンテナ内にもgooseを導入してあります。

原因

コンテナ内では外部ファイルやコマンドで指定してあげないと、環境変数を読み込むことができないみたいです。
コンテナ内を確認したところ、.envがコピーされていなかったので、Dockerの使用上コピーできないようになっているんですかね?
Docker で環境変数をホストからコンテナに渡す方法(ホスト OS 側からゲスト OS に渡す方法各種)

解決

docker-compose.ymlにオプション追加

version: "3.7"

services:
  server:
    container_name: server
    build:
      context: ./
      dockerfile: Dockerfile.dev
    ports:
      - 8000:8000
    env_file:  # 左記オプション追加
      - .env
    depends_on:
      - db
    tty: true
    stdin_open: true
    volumes:
      - ./:/go/src/server
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む