20190821のdockerに関する記事は14件です。

RancherOS + compose + portainer.io でお手軽 GUI docker stack 入門環境

はじめに

コンテナ専用OSのなかでもRancherOSはisoサイズが極端に小さいため始めるのも肩がこらず楽ちんです。

ディストリビューション amd64 iso size
CoreOS Container Linux 2135.6.0. 423MB
CentOS Atomic Host 2019-Jul-2 1.1GB
Fedora Atomic Host 20190820 1GB
Rancher OS 1.5.3 127MB

※ Ubuntu Coreはisoがないが、amd64用イメージは340MB

コンテナオーケストレーション環境Rancherの影響から、Kubernetesと組み合わせての利用が多い様子ですが、単にdockerだけで使うにも便利です。各種のディストリビューションコマンドセットを切り替えて使えるので、RedHat派/Debian派/Ubuntu派 問わず使える点も魅力。

今回は、潔くKubernetesは捨てて、portainerをGUIとしたdocker-composeを使ったコンテナスタック入門環境を構築する手順を紹介します。慣れれば5分で終わります。

環境

  • Rancher OS v1.5.3
  • portainer 1.22.0

記事を書くにあたり、VirtualBox 6.0上に環境を用意して作業していますが、別の環境でも特に変わりありません。

手順概略

  1. Rancher OS インストール & 設定
  2. portainer 導入、起動、httpでアクセス

Rancher OS に docker-compose コマンドはないのですが、導入は不要です。これは、portainerが内部にlibcomposeを持っており自力でcomposeを実行できるからのようです。Rancher OSにdocker-composeをインストールしてもコンソールを切り替えると消えてしまい、これの対策は逆に面倒なので、Rancher OS上でdocker-composeを直接扱うよりも便利な点。

1. Rancher OS インストール & 設定

iso から Rancher OSを起動

https://github.com/rancher/os/releases/tag/v1.5.3 からrancheros.isoをダウンロード。CDに焼くなりブートUSBを作るなりして、起動。

rancheros_isoboot.png
起動するとログイン状態になるので、SSHの準備として一時ログイン用パスワードを設定する。このとき設定するパスワードは使い捨てるため、深く考えなくてもよい。

[rancher@rancher ~]$ sudo passwd rancher
# 適当なパスワードを設定

ここで設定したアドレスを使って、SSHログイン。ユーザ名は rancher

> ssh -l rancher -p 22 <host_address>

インストール設定を流し込む

sshターミナル上で、

[rancher@rancher ~]$ vi cloud-config.yml
cloud-config.yml
hostname: ros001
# ファイルがないと怒られるので何か書いておく
# 必要であればほかの設定も追加

ここでは、ネットワークアドレスはDHCP設定を前提にしている。ここでネットワーク設定を済ませる場合は、公式リファレンス を参照のこと。
cloud-config.yml の文法チェックをしておく。エラーが出たら修正しておくこと。

[rancher@rancher ~]$ sudo ros config validate -i cloud-config.yml
# 何も表示されなかったら文法チェックOK

ディスクにインストール

先にインストール先のディスクを確認しておく。

[rancher@rancher ~]$ sudo fdisk -l 
Disk /dev/sda: 8 GiB, 8589934592 bytes, 16777216 sectors 
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

例えばこんな風に出たら、インストール先は /dev/sda なので、次のコマンドを打ってディスクへインストールする。

[rancher@rancher ~]$ sudo ros install -c cloud-config.yml -d /dev/sda --append="rancher.password=<localpassword>"

--append="rancher.password=password" の部分は、パスワードログインのために必須。ここで設定するパスワードは、ディスクにインストールされたシステムのログインパスワードとなるため、慎重に決めること。うまくいけば再起動がかかる。ブートディスクをアンマウントして、ディスクにインストールされたRancher OSを起動する。

インストール後の設定

インストール後、SSHでログインする際に、

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.

などと出てくることがある。インストール時にSSHログインした際のfingerprintが残っていることが原因なので、SSHクライアント側PCの~/.ssh/known_hosts を開いて、当該項目を消せば治る。

設定すべき項目は特にないが、ネットワーク回り等で追加設定がある場合はここで済ませておく。また、セキュリティの問題がある環境の場合はSSHログインを鍵認証にしておく。設定の方法は2種類あって、

  • sudo ros config set ... : 設定コマンドを使う
# 設定例
[rancher@ros001 ~]$ sudo ros config set rancher.network.interfaces.eth0.dhcp false
  • vi /var/lib/rancher/conf/cloud-config.yml : ファイルの直接編集
/var/lib/rancher/conf/cloud-config.yml 設定例
rancher:
  network:
    interfaces:
      eth0:
        dhcp: false

は同じ意味になる。ymlを直接編集する場合は、文法チェックを必ず行う。

[rancher@ros001 ~]$ sudo ros config validate -i /var/lib/rancher/conf/cloud-config.yml

いずれの場合も、設定変更後は再起動が必要。

なお、

  • 設定を確認するには $ sudo ros config export コマンドを使う
  • 項目を削除するためのコマンドはないので、削除が必要なら /var/lib/rancher/conf/cloud-config.yml を直接編集

詳しくは リファレンスマニュアル 参照

portainer.io の実行

$ docker run -d -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

http://<ホストアドレス>:9000 にアクセス

こんな画面が出たら、起動中なので少し待つ。
image.png

うまく起動すればadminパスワード設定画面が出る
image.png

今回はローカルのdockerを管理したいので、Localを選ぶ
image.png

local をクリックして、
image.png

Stacks → Add stack をクリック
image.png

Nameを入力する際に、現在、英子文字以外のあらゆる記号、大文字を使うとstackの管理が狂う不具合があるため、a-zのみで入力する。参照
下のエディタにdocker-compose.ymlの中身を入力するか、docker-compose.ymlをアップロードする。下の方のDeploy the stackボタンを押せば、ネットワーク設定が正しければ問題なくデプロイできるはず。
image.png

ここまで慎重に進めても15分程度。あとはほとんどの設定がportainer上で可能です。

Tips

Rancher OSの console 設定について

https://rancher.com/docs/os/v1.x/en/installation/configuration/switching-consoles/ に詳しい。

$ sudo ros console list

で出てきたものなら、 何を選んでもよい。default コンソールはコマンドが少ないので、別のものを選ぶとよい。コンソールを切り替えると /home /opt /var/lib/docker /var/lib/rancher 以外のデータはすべて消えてしまうので注意。

参考文献

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

DockerでRedmineのSystem Testを動かしてみた

業務でRedmineのPlugin開発をしているのですが、
せっかくDocker上で開発しているので、System TestもDocker上で実行できないかと思い試行錯誤してみました。

Dockerで環境を整える

まず、ディレクトリの構成です。

ディレクトリ構成
workspace/
 ├── Dockerfile
 ├── docker-compose.yml
 ├── docker-compose-dev.yml
 ├── docker-sync.yml
 ├── docker-compose-test.yml
 ├── entrypoint.sh
 ├── redmine/
 └── postgers/

redmineここからclone。
postgresディレクトリは、docker-composeでコンテナを起動すれば勝手に作成されるはず。
postgres以下にはPostgreSQLのデータが保存されます。

各ファイルの内容です。

Dockerfile

基本のDockerfile

今回はruby:2.5のイメージを使用します。

Dockerfile
FROM ruby:2.5

RUN gem install bundler
RUN mkdir /redmine
WORKDIR /redmine
ENV BUNDLE_PATH /redmine/vendor/bundle
ENV RAILS_ENV development

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]1

redmineは後からvolumeするのでイメージの中ではディレクトリを作成するだけです。

実際はRedmineもイメージに追加して、filespluginsだけvolumeする方がいいかもしれません。
開発用の環境なので、環境変数はENV RAILS_ENV developmentを指定します。

entrypoint.sh

イメージの作成に使います。
公式のRails用のサンプルを参考にしています。(https://docs.docker.com/compose/rails/)

sh
#!/bin/bash
set -e

rm -f /redmine/tmp/pids/server.pid

exec "$@"

docker-compose.yml

Redmineの開発環境用のdocker-compose.ymlです。

docker-compose.yml
version: '3'

services:
  redmine:
    build: .
    image: redmine:4
    environment:
      BUNDLE_PATH: /redmine/vendor/bundle
      RAILS_ENV: development
      DB_HOST_NAME: postgres
    volumes:
      - ./redmine:/redmine
    ports:
      - 3000:3000
    depends_on:
      - postgres
  postgres:
    image: postgres:9.6
    volumes:
      - ./postgres:/var/lib/postgresql/data

image:属性を指定すると、docker-composeでbuildしたイメージの名前を指定できます。
BUNDLE_PATHRAILS_ENVDockerfileで指定しているのでここで指定する必要はありません。

docker-compose-dev.yml

docker-sync用の設定です。

System Testはかなり遅いので、docker-syncは使用した方がいいと思います。
docker-syncは別にインストールする必要があります。

docker-compose-dev.yml
version: '3'

services:
  redmine:
    volumes:
      - redmine4_volume:/redmine
  postgres:
    volumes:
      - redmine4_postgres_volume:/var/lib/postgresql/data

volumes:
  redmine4_volume:
    external: true
  redmine4_postgres_volume:
    external: true

servcesにはdocker-compose.ymlでの設定と変更したい属性と追加したい属性のみを記述します。

volumesにはdocker-syncで定義するvolumeの名前を宣言します。

docker-sync.yml

docker-syncの設定ファイルです。

docker-sync.yml
version: '2'

syncs:
  redmine4_volume:
    src: './redmine'
    sync_strategy: 'unison'
  redmine4_postgres_volume:
    src: './postgresql_data'
    sync_strategy: 'unison'

srcは相対パスで記述してますが、絶対パスで書いた方が安心だと思います。

docker-sync.ymlは拡張子をyamlにしたら起動できませんでした。

docker-compose-test.yml

test環境用のcomposeファイルです。

docker-compose-test.yml
version: '3'

services:
  redmine:
    environment:
      RAILS_ENV: test
    depends_on:
      - chrome
  selenium-hub:
    image: selenium/hub:3.141.59-selenium
    ports:
      - 4444:4444
  chrome:
    image: selenium/node-chrome-debug:3.141.59-selenium
    shm_size: 2g
    depends_on:
      - selenium-hub
    environment:
      - HUB_HOST=selenium-hub
      - HUB_PORT=4444
    ports:
      - 5900:5900

RAILS_ENVはテスト環境なのでtestに変更します。

chromeはchromeドライバです。
redmineのシステムテストを動かすために必要です。
selenium-hubがどうして必要なのか、まだ理解できてないんですが、多分chromeを使うために必要なんじゃないかと思ってます。

Redmineを起動します。

Terminal
$ cd /path/to/workspace
$ docker-compose build
$ docker-compose run --rm redmine bundle install
$ docker-compose run --rm redmine bundle exec rake db:create db:migrate

Redmineの環境が整うまでRedmineの起動ができないのでrunコマンドを使用して環境を整えます。
--rmオプションはrunコマンドで作成されたコンテナを削除するためのコマンドです。

ここまででRedmineの準備は完了です!

System Testを動かす

まずはコンテナ間でネットワークが繋がっているかどうかの確認です。

docker-syncを起動して起きます。

Terminal
$ docker-sync start

chrome側からRedmineが見えるか確認

chromeとRedmineが繋がっているのか確認したかったので、まずはchromeのコンテナからRedmineにアクセスできるかを確認します。

まずはRedmineを起動。

$ docker-compose -f docker-compose.yml -f docker-compose-dev.yml up

Redmineを起動したらホストのブラウザを立ち上げて、アドレスバーにhttp://localhost:5900を入力します。
画面共有をするか聞かれるのでOKを選択。
パスワードを聞かれたらsecret、黒い画面が立ち上がるはずです。

起動した画面上で右クリック → Application → Network → chrome。chromeコンテナ上のchromeが起動できます。

立ち上げたchromeのアドレスバーにhttp://redmine:3000を入力するとRedmineにアクセスできます。
URLのredminedocker-compose.ymlで指定したサービス名です。
Redmineの画面が表示されれば成功です。一度コンテナを落とします。

$ docker-compose down

RedmineのTestファイルを修正

Redmineのシステムテストの設定を、dockerコンテナ上で動くように変更します。

RailsのAPIとか
actionpack-5.2.3/lib/action_dispatch/system_testing/driver.rbactionpack-5.2.3/lib/action_dispatch/system_testing/browser.rbのソースを参考にしながら
application_system_test_case.rbの設定を追加してみました。

redmine/test/application_system_test_case.rb
  driven_by :selenium, using: :chrome, screen_size: [1024, 900], options: {
      desired_capabilities: Selenium::WebDriver::Remote::Capabilities.chrome(
        'chromeOptions' => {
          'prefs' => {
            'download.default_directory' => DOWNLOADS_PATH,
            'download.prompt_for_download' => false,
            'plugins.plugins_disabled' => ["Chrome PDF Viewer"]
          }
        }
      ),
      browser: :remote,
      url: 'http://selenium-hub:4444/wd/hub'
    }

  setup do
    clear_downloaded_files
    Setting.delete_all
    Setting.clear_cache
    Capybara.app_host = 'http://redmine:3000'
  end

driven_byの引数のハッシュに、ブラウザの種類browser: :remote
ブラウザのURLurl: 'http://selenium-hub:4444/wd/hub'を追記。

setupのブロックの中にapplicationのホストCapybara.app_host = 'http://redmine:3000'を追記します。

テスト実行

Terminal
$ docker-compose -f docker-compose.yml -f docker-compose-dev.yml -f docker-compose.test run --rm redmine bundle exec rake test:system

以下のエラーが出て動きませんでした。

Terminal
NameError: uninitialized constant ApplicationSystemTestCase::Selenium
/redmine/test/application_system_test_case.rb:26:in `<class:ApplicationSystemTestCase>'
/redmine/test/application_system_test_case.rb:22:in `<top (required)>'

エラーになった部分をdesired_capabilities: :chromeに書き換えます。

redmine/test/application_system_test_case.rb
  driven_by :selenium, using: :chrome, screen_size: [1024, 900], options: {
      desired_capabilities: :chrome,
      browser: :remote,
      url: 'http://selenium-hub:4444/wd/hub'
    }

再度実行。

Terminal
Run options: --seed 45718

# Running:
...

何故か動きました。
エラーの内容は調査しきれな買ったのでまた次回。

テストの実行結果はこんな感じです。

Terminal
Run options: --seed 45718

# Running:

Capybara starting Puma...
* Version 3.12.1 , codename: Llamas in Pajamas
* Min threads: 0, max threads: 4
* Listening on tcp://127.0.0.1:42831
.[Screenshot]: tmp/screenshots/failures_test_project_quick_search.png
E

Error:
QuickJumpTest#test_project_quick_search:
Capybara::ElementNotFound: Unable to find link or button "Megaproject" within #<Capybara::Node::Element tag="div" path="/HTML/BODY[1]/DIV[1]/DIV[2]/DIV[1]/DIV[2]">
    test/system/quick_jump_test.rb:64:in `block in test_project_quick_search'
    test/system/quick_jump_test.rb:60:in `test_project_quick_search'


bin/rails test test/system/quick_jump_test.rb:54

.E

Error:
MyPageTest#test_add_block:
Net::ReadTimeout: Net::ReadTimeout
    test/system/my_page_test.rb:64:in `test_add_block'

Error:
MyPageTest#test_add_block:
Net::ReadTimeout: Net::ReadTimeout



bin/rails test test/system/my_page_test.rb:57

とりあえずテストを動かせるところまでは成功しましたが、テストは失敗しました。
エラーがいっぱい出てます。

でもとりあえず動かせたから今回はここまでにします。

文章にするのは難しいですね。

参考

https://qiita.com/yutachaos/items/4a1da5d55a3bf0df889e

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

Photogrammetry on Docker ~ サーバ屋さんもXRしたい ~

フォトグラメトリとは?

最近,このような動画がバズっていました.

鎌倉の銭洗弁天という場所を"フォトグラメトリ"という技術を用いて作られたようです.

フォトグラメトリとは、物体を様々な方向から撮影した写真をコンピューターで解析し、3Dモデルを立ち上げる技術です。
フィギュアのような小さなものから、建築や都市といった大きなものまで3Dモデルにすることができます。

引用:フォトグラメトリ入門 撮影方法~3Dモデル作成

ざっくりというと,写真から3Dモデルを生成する技術です.
最近,私がxRTech Tokyoに参加し,そういや,3か月前くらいにOSSのフォトグラメトリのソフト使ったことあったなーということを思い出し,やる気のあるうちに,フォトグラメトリを簡単に行うDockerイメージを作りました.

リポジトリ

今回作ったDockerのリポジトリ

https://github.com/kotauchisunsun/alpine-mve

今回,Docker用に改造したフォトグラメトリのソフトのリポジトリ

https://github.com/kotauchisunsun/mve

利用方法

手軽に行いたい方はこちら

$ mkdir image # ここにフォトグラメトリの対象となる画像を置く
$ mkdir scene # ここに3Dのモデルが出力される
$ sudo docker run --rm -it --privileged -v `pwd`/image:/image -v `pwd`/scene:/scene kotauchisunsun/alpine-mve ./run.sh 

これでscene/surface-L2-clean.plyに3Dモデルが生成されます.
これだけです!

自分でビルドしたい方はこちら

$ mkdir image # ここにフォトグラメトリの対象となる画像を置く
$ mkdir scene # ここに3Dのモデルが出力される
$ sudo docker build -t kotauchisunsun/alpine-mve https://github.com/kotauchisunsun/alpine-mve.git
$ sudo docker run --rm -it --privileged -v `pwd`/image:/image -v `pwd`/scene:/scene kotauchisunsun/alpine-mve ./run.sh 

速度を求めたい人は自分でcloneしてきて自分のCPUに最適化したDockerイメージを作るのをお勧めします.

サンプルの出力結果

自分が3Dとして取り出したい対象の写真を撮って利用することもできますが,ここでは,
Agisoftさんのサンプルのmonumentというデータを使った出力結果を張り付けておきます.

zipの元の画像データはこんな感じ
image.png

出力された3Dデータ
image.png

斜めのアングル
image.png

後ろ姿ももちろん見える
image.png

視点が届きにくい上からのポリゴンは削れがち
image.png

OSSのPhotogrammetryソフト

今回利用したのはドイツのダルムシュタット工科大学が作ったMVEというソフトです.

https://github.com/simonfuhrmann/mve

それを,私が今回用にちょっとビルド回りをいじったものを使っています.

https://github.com/kotauchisunsun/mve

OSSのPhotogrammetryソフトを色々と使ってみた結果,自分には一番MVEがあってる!となったので,その理由を紹介したいと思います.

CPUのみで動く

一番の理由がCPUのみで動くことです.高品質なOSSで無料のフォトグラメトリのソフトにMeshRoomというものがあります.

image.png

割と評判もよいので,使ってみたところ,NVidiaのGPUが必須のようで,intelのGPUのノートPCでは動きませんでした.したがって,CPUベースのフォトグラメトリソフトを探す必要がありました.

速い

もう1つ高精度なフォトグラメトリのソフトとして,COLMAPというものがあります.

image.png

これも非常にきれいに出力ができて,なおかつCPUで動く.ということで割と評判が良かったので導入してみました.私のPCでは遅すぎて出力が終わらなかったです.これは,悪い点ではあるのですが,おそらく発想が逆で,アルゴリズムがGPU特化しているせいで,それを無理にCPUで回そうとすると膨大な時間がかかってしまっている.というのが原因だと思います.私のPCが悪い.
一方で,先ほどのmonumentのサンプルを動かしてもMVEだとCPUでも1時間未満ぐらいで動いたので,非常に手軽でした.

1パッケージ

その他にも,色々とのフォトグラメトリのソフトはいろいろあり,VisualSFMなど色々あります.これも試してみました.しかし,以下の図を見ていただくと分かるのですが,選ぶソフトによっては,そのソフトで完結せず,複数のソフトを経由するものがあり,非常に煩雑です.

image.png

引用:http://www.cs.cmu.edu/~reconstruction/Documentation.html

これを見ると分かるようにMVEは1つのソフト(リポジトリ)ですべてのワークフローが完結するので,非常に楽です.

まとめ

  • MVEというフォトグラメトリを行うソフトが簡単に動くDockerイメージを作りました.
  • MVEはCPUだけでフォトグラメトリが出来て,そこそこ短時間で3Dモデルが作れます.
  • 実際にサンプルの画像から3Dモデルが取り出せました.

感想

5年ほど前に,3Dスキャナを作ってたこともあり,このあたりの技術には非常に興味がありました.その当時はAutodesk 123D Catchぐらいしかなく,このような画像特徴量ベースのものはかなり少なかったです.その当時から考えると凄く世の中変わったなーと思います.商用のものと比べれば,まだまだかもしれませんが,サーバー屋さんでも手軽にフォトグラメトリできます.時間は結構かかるので,さくらのVPSとかで動かして,寝て待つのがいいのでしょうかね.

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

Dockerを使ってみよう-1

この記事は Dockerを分かった気になれる Dockerのコンセプトとかあまり紹介しないまま、脳死コピペでなんとかいける仕様になってます。今回はDockerをインストールし、コンテナを作って起動させるところまで書きます。
次回はAWSのECRにコンテナをプッシュする作業について書きたいと思います。

仕事でDockerを使えって言われたけど、どこから手を付ければいいのか分からなかった数日前の自分のために…

環境

・Amazon Linux AMI 2018.03.0 (HVM)
・Docker CE
・ポート4000

Dockerをインストール

最初からスーパーユーザーになってたら楽かもしれませんね。

アプデ
sudo yum update
インストール
sudo yum install docker -y
Docker起動
sudo service docker start

Docker Imageを作成

ここではDockerfilerequirements.txtapp.pyのファイルを三種類を作り、編集していきます
以下のコードはDocker公式のドキュメントから拝借しています。リンクは記事の一番下にあるのでぜひ見に行ってくださいね!
コードの詳細が書かかれてますよ(英語)

ファイルを作成

touch Dockerfile

内容はこれに編集します

Dockerfile
# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR/app

# Copy the current directory contents into the container at /app
COPY. /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-hostpypi.python.org -rrequirements.txt

# Make port 80 available to the world outside this container
EXPOSE80

# Define environment variable
ENVNAME World

# Run app.pywhen the container launches
CMD["python", "app.py"]

requirements.txtも作り、編集していきます

requirements.txt
Flask
Redis

app.pyも同様です

app.py
from flask import Flask
from redis import Redis,RedisError
import os 
import socket
# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app=Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>"\
            "<b>Hostname:</b> {hostname}<br/>"\
            "<b>Visits:</b{visits}"
   return html.format(name=os.getenv("NAME","world"),
hostname = socket.gethostname(), visits=visits)

if__name__=="__main__":

    app.run(host='0.0.0.0',port=80)

Dockerを走らせます

いよいよですよ…

まずはビルドから

friendlyhelloのタグをつけてやりますので、タグの名前を変更しても大丈夫です

docker build -t friendlyhello .

Docker imagesでビルドを確認します

docker images

先ほどつけた名前がREPOSITORYの下にでますので、ちゃんとありましたら走らせます!!!!
ポート4000を使うのでEC2インスタンスの方でもちゃんと開けておいてくださいね

docker run -p 4000:80 friendlyhello

アウトプットに'#Running on http://0.0.0.0.80/ (Press CTRL+C to quit)' がでましたら、インスタンスのPublic IP アドレスとポート番号を指定して実際にHello World!が表示されてるか確認しにいきましょう

簡単にいうとこんな感じです↓
http://your_public_ip:4000/

参考にしたサイト

この記事で使用したコードはDocker公式のご提供です
https://docs.docker.com/get-started/part2/

アマゾンさんは日本語に対応していますので
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/docker-basics.html

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

RailsのノリでDockerを使ってNginx+Laravelの環境を作ろうとしたらハマった話

概要

DockerでNginx + Laravelの環境を作ろうとしたらハマったのでまとめました。
仕組みを知るって大切ですね。

ハマった経緯

Railsで下記のような構成のアプリケーションを触っていたため、Nginx+Laravelでもいけるだろと思ったらハマった。

Railsの構成(成功)

rails-rp.png

Laravelの構成(失敗)

laravel-failed.png

何故ハマったかの結論

PumaはWebサーバであるが、PHP-FPMはWebサーバではないから静的ファイルを返さなかった!
当たり前の話なんでしょうけど、コピペで動けばいいやでやってるといずれハマるものですね・・・。

じゃあどうするのが正解?

前提

  • Dockerを利用した場合で考えるので、1コンテナ1プロセスとして設計する (Logを収集しやすかったりといろいろと利点がありますよね)
  • 本番環境はKubernetesを利用する

開発環境パターン1(ネット上でよく見るやつ)

NginxとLaravelでソースを共有して静的ファイルを返すパターン
今回ハマってなんで動くのかよく理解ができました・・・!
laravel-success1.png

開発環境パターン2(静的ファイルを分離)

静的ファイルを別サーバで返すようにするパターンです。
LaravelをAPI化してSPAと連携する場合などはこっちの方がよいと思います。(本番でFirebaseとかに投げれるし)
※ LocalではBackendとFrontendを別ディレクトリとしてmountする。
laravel-success2.png

本番環境パターン1(開発環境パターン1に近い形)

1Podに3コンテナはちょっと美しいとは言えないけどFrontとBackをわけていない場合はこれでいいと思います。
laravel-kubernetes1 (1).png

本番環境パターン2(開発環境パターン2に近い形)

開発環境パターン2のようにFrontとBackで分けている場合はこのような構成がいいと思います。
FrontendはFirebaseなどに投げるのもありだと思います。
あとは調査が足りてませんが、頑張ればingress-nginxでfastcgiの対応が可能かもしれません。
laravel-failed (1).png

まとめ

  • PHP-FPMはFastCGIで動作するミドルウェアであり、WebサーバではないためNginxと連携して静的ファイルを返す仕組みが必要になる
  • 上手く連携させるためには2パターンある(サーバを分離しないのも含めると3パターン)
    1. ソースを共有できる場所を用意してNginxでそちらを参照する
    2. 静的ファイルをPHP-FPMサーバから分離する
      • RPサーバに置く事も可能だが、役割を考えると専用にサーバを用意した方がよい

参考文献

Webサーバ、FastCGI、Unixドメインソケット、TCPソケットについて詳しく書かれています
https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc

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

Dockerコンテナ内から同一ホストの別コンテナにホストを経由してアクセスできない

世の中、覚えなければ上手く行かないことが多すぎる。だから、全てを覚えてから始めるんじゃなくて、やってみて失敗してから掘り下げるアプローチが好きです。まどかママの「上手な転び方を覚え」るってのは至言だと思う。

そんな訳で、Keycloakで認証を行うWebアプリを開発していて、動作確認も終わり、いざ検証環境で動かそうとしたら、Webアプリの起動が失敗してしまった。

システムの構成と経緯は以下のようなイメージ。

  • Keycloakサーバは、検証環境でdocker-composeを使って構築。
  • Webアプリは、バックエンドをSpring Boot、フロントエンドをAngularで開発。

    • Angularアプリではkeycloak-angularを使用。
    • Spring Bootアプリはリソースサーバとして動作するのでspring-boot-starter-oauth2-resource-serverを使い、Angularアプリから送られてきたトークンを検証。
  • 開発中は、検証環境のKeycloakサーバに接続して動作を確認。

  • Webアプリをコンテナにして、検証環境のKeycloakサーバと同じホストのDocker上で起動すると、Spring BootアプリからKeycloakサーバへの経路がない(no route to host)とのエラーで終了していた。

まず試したこと

そこでKeycloakコンテナとWebアプリコンテナを同じDockerネットワークに参加させ、Spring BootアプリからDockerネットワーク経由で接続するようにしてみた。

  1. docker network create ${ネットワーク名}でネットワークを作成。
  2. KeycloakとWebアプリのdocker-compose.ymlで、上記のネットワークに参加するように設定。
例)Webアプリのdocker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
    container_name: app
    ports:
      - 50010:8080
    networks:
      - ${ネットワーク名}
networks:
  ${ネットワーク名}:
    external: true
SpringBootアプリのapplication.yml
spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://${keycloakコンテナ名}.${ネットワーク名}:8080/auth/realms/${レルム名}

これでSpring Bootアプリは、Keycloakサーバと通信が成功して、正常に起動するようにはなった。
が、Angularアプリでログインを行うと、keycloakサーバへのログインに成功するものの、その後でAngularアプリからSpring BootアプリへのAjax通信で 401 Unauthorizedとなってしまった。

ブラウザでレスポンスを見てみると、ヘッダに以下の情報があった。

WWW-Authenticate: Bearer error="invalid_token",
                  error_description="This iss claim is not equal to the configured issuer", 
                  error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"

どうやらAngularアプリとSpring BootアプリがアクセスするKeycloakサーバのURLは一致していないとのこと。
なので、どうしてもDockerコンテナ内部から外部ネット経由でアクセスする必要だった。

根本の原因

そこでネットから情報を漁ると、Dockerがiptablesを設定していて、それによって通信ができないらしい。
こちらの記事とか参考にしてiptablesの見方を勉強してみた。
まだ完全に理解できていないが、自ホストからパケットを送信する場合のチェインを辿ってみると、、、

# iptables -t nat -nvL POSTROUTING
Chain POSTROUTING (policy ACCEPT 12 packets, 853 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0
 ※あとは割愛

Dockerkコンテナにデフォルトで割り当てられるbridgeネットワークのアドレス172.17.0.0/16からの通信は、docker0ブリッジには戻れない設定だと思えた。

回避策

現状の理解ではiptablesを弄るのもハードルが高いので、WebアプリのDockerコンテナがデフォルトのbridgeドライバを使ったネットワークではなく、hostドライバを使うように指定した。

docker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
    container_name: app
    network_mode: host     # 追加
# ポートマッピングは使えなくなるので削除
#    ports:
#      - 50010:8080

これによりコンテナ内部で使うポートが、直接ホストで使われてしまうが、そこはSpring Bootの設定ファイルで簡単にポート番号を変更できるので良しとしました。

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

【Airflow on Kubernetes】トラブルシューティング - AttributeError: '_jpype.PyJPField' object has no attribute 'getStaticAttribute'

概要

JPype1==0.7.0を利用してJdbcOperator()を実行すると表題のエラーが出力される。

目次

バージョン

DAG

一部抜粋

from airflow.operators.jdbc_operator import JdbcOperator

sql_task = JdbcOperator(
    task_id='sql_cmd',
    jdbc_conn_id='my_connection_id',
    #template_searchpath='/etc/dev/airflow/templates',
    #sql=['sample.sql'],
    sql=['select id,name from sample_table'],
    params={"db":'MY_DBNAME'},
    dag=dag
)

エラー詳細

ログの見方:DAGの実行結果ログを確認する

[2019-08-21 09:30:48,913] {taskinstance.py:1047} ERROR - '_jpype.PyJPField' object has no attribute 'getStaticAttribute'
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/airflow/models/taskinstance.py", line 922, in _run_raw_task
    result = task_copy.execute(context=context)
  File "/usr/local/lib/python2.7/dist-packages/airflow/operators/jdbc_operator.py", line 63, in execute
    self.hook.run(self.sql, self.autocommit, parameters=self.parameters)
  File "/usr/local/lib/python2.7/dist-packages/airflow/hooks/dbapi_hook.py", line 159, in run
    with closing(self.get_conn()) as conn:
  File "/usr/local/lib/python2.7/dist-packages/airflow/hooks/jdbc_hook.py", line 51, in get_conn
    jars=jdbc_driver_loc.split(","))
  File "/usr/local/lib/python2.7/dist-packages/jaydebeapi/__init__.py", line 381, in connect
    jconn = _jdbc_connect(jclassname, url, driver_args, jars, libs)
  File "/usr/local/lib/python2.7/dist-packages/jaydebeapi/__init__.py", line 183, in _jdbc_connect_jpype
    types_map[i.getName()] = i.getStaticAttribute()
AttributeError: '_jpype.PyJPField' object has no attribute 'getStaticAttribute'

対策

JPype1==0.6.3ではエラーにならないのでダウングレードをする。

参考

https://github.com/baztian/jaydebeapi/issues/99

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

Ubuntsu + Docker + Gitlabを動かす

導入

開発サーバとして運用しているUbuntsu上にDockerをインストールし、その中でGitlabを動かしたい

やったこと

dockerのインストール

command
sudo apt-get install docker

gitlabのイメージでrun

command
docker run --detach ` //バックグラウンドで起動する
    --hostname gitlab.example.com `
    --publish 8080:8080 `
    --name gitlab `
    --restart always `
    --volume /srv/gitlab/config:/etc/gitlab `
    --volume /srv/gitlab/logs:/var/log/gitlab `
    --volume /srv/gitlab/data:/var/opt/gitlab `
    gitlab/gitlab-ce:latest

はまりごと

どうもbad gatewayで動かない
unicornというパッケージがポート8080を使用していた

/etc/gitlab/gitlab.rb
unicorn['port'] = 8090

参考

https://qiita.com/TaskeHAMANO/items/b01f2d8590c23d6b2bce
https://maku77.github.io/git/gitlab/unicorn-port.html

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

Overlay2 について調べてみた

作業時のメモ

Docker の StorageDriver の一つである Overlay2 について調べた・動きを検証したときのメモ。

どういう仕組み?

Overlay2/Overlay は OverlayFS という仕組みを利用している

実践! OverlayFS

OverlayFSの基礎
ドキュメントには色々書いているが、Overlayfsの基本的な考え方は以下の通り
Readonlyな下の層と、Writableな上の層を重ね合わせ1つのファイルシステムに見せる
このとき、ディレクトリは重ね合わされ、ファイルは上から見ていく
コンフリクトしていたらファイルだと上が優先され、ディレクトリだとマージされる
下(readonly)にしかないファイルを編集すると上にコピーが作成される

Docker の公式ページにも Overlay/Overlay2 の説明がある
イメージ図があるが Overlay のものなので注意。

Use the OverlayFS storage driver

The overlay2 driver natively supports up to 128 lower OverlayFS layers. This capability provides better performance for layer-related Docker commands such as docker build and docker commit, and consumes fewer inodes on the backing filesystem.

上記ドキュメントにも記載があるが overlay2 は複数の lower layer をサポートしている。
利用イメージ例は以下のようになる

Container Storage Best Practices in 2017 p21

これを見るとイメージがしやすい。
上記にそれぞれの StorageDriver の Pros/Cons も書いてある。

動きを検証

環境

docker info
Containers: 42
 Running: 4
 Paused: 0
 Stopped: 38
Images: 26
Server Version: 18.06.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:
 seccomp
  Profile: default
Kernel Version: 4.14.77-80.57.amzn2.x86_64
Operating System: Amazon Linux 2
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 985.7MiB
Name: ip-172-31-30-50.ap-northeast-1.compute.internal
ID: M5OF:USUI:CHU4:NPLX:6TPC:DJ52:6C6O:DEHT:2BUM:WDHN:DSCO:HFHD
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

コンテナを作る

$docker run -d alpine sleep 10000
8c22dfe56161d277ffe02bef504848a88ec759c7d28d4259570a25f4401b04a6

# 配置場所を確認
$docker inspect 8c22dfe56161 |less

        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff:/var/lib/docker/overlay2/b88590da7d8e2e35c9b4f7368017760575b71c95f5ff68b7ee8dfc86f9fc7a66/diff",
                "MergedDir": "/var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/merged",
                "UpperDir": "/var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff",
                "WorkDir": "/var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/work"
            },
            "Name": "overlay2"
        },

LowerDir

LowerDir は2つなので Layer は2つということだと思われる

  • /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff
  • /var/lib/docker/overlay2/b88590da7d8e2e35c9b4f7368017760575b71c95f5ff68b7ee8dfc86f9fc7a66/diff

Alphine の Dockerfile

alpinelinux/docker-alpine

FROM scratch
ADD alpine-minirootfs-3.10.2-x86_64.tar.gz /
CMD ["/bin/sh"]

確かに2つぽい

それぞれ見てみる

$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/
dev  etc

$sudo ls /var/lib/docker/overlay2/b88590da7d8e2e35c9b4f7368017760575b71c95f5ff68b7ee8dfc86f9fc7a66/diff/
bin  etc   lib    mnt  proc  run   srv  tmp  var
dev  home  media  opt  root  sbin  sys  usr

Github から 「alpine-minirootfs-3.10.2-x86_64.tar.gz」を落とすと「/var/lib/docker/overlay2/b88590da7d8e2e35c9b4f7368017760575b71c95f5ff68b7ee8dfc86f9fc7a66/diff/」と同じ構成だった。

別のコンテナでも確認してみる。

超軽量 Docker Image true (125 bytes) と sleeping-beauty (129 bytes)

$docker run -d tianon/sleeping-beauty

$ docker inspect d00b12c14095 |less

        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b-init/diff:/var/lib/docker/overlay2/4e31a13b0f9f31f90d2dc4a5c19d5f4e87788fefb29e8b550005ba4a984ca4f6/diff",
                "MergedDir": "/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/merged",
                "UpperDir": "/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/diff",
                "WorkDir": "/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work"
            },
            "Name": "overlay2"
        },

$sudo ls /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b-init/diff
dev  etc  proc  sys

$sudo ls /var/lib/docker/overlay2/4e31a13b0f9f31f90d2dc4a5c19d5f4e87788fefb29e8b550005ba4a984ca4f6/diff
sleeping-beauty

Dockerfile はこうなっていた

FROM scratch
COPY sleeping-beauty /
CMD ["/sleeping-beauty"]

「-init 」というのは scratch ということで良さそうだが差分が有るのは Dockerhub に Push された際の scratch の構成の違いなのかも。

UpperDir

コンテナは起動しただけで container layer(read/write)には何も書き込みをしていないので空っぽ。

$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/

WorkDir

work というフォルダがあるぐらいで空っぽ

sudo tree /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
`-- work

1 directory, 0 files

MergedDir

alphine コンテナ。

$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/merged/
bin  etc   lib    mnt  proc  run   srv  tmp  var
dev  home  media  opt  root  sbin  sys  usr

「sleeping-beauty」の方が分かりやすいのでこちらも確認。

sudo ls /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/merged/
dev  etc  proc  sleeping-beauty  sys

LowerDir の Scratch の Layer のファイルに sleeping-beatuty が追加されている。

コンテナにファイルを作る

コンテナにファイルを作ってどうなるか変化を見てみる。
先程起動した alphine コンテナを利用する。

# コンテナにファイルを作成
$docker exec 8c22dfe56161 touch /tmp/hoge

# UpperDir に追加されている
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/tmp/
hoge

# MergedDir にも確認出来る
$ sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/merged/tmp/
hoge

コンテナを停止する

コンテナを停止させる。

# 停止
$docker stop 8c22dfe56161
8c22dfe56161

# SIGKILL で止まって終了ステータスコード 137 ぽい
$docker ps -a |grep 8c22dfe56161
8c22dfe56161        alpine                           "sleep 10000"            34 minutes ago       Exited (137) 25 seconds ago                         reverent_leavitt

# LowerDir はある
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/
dev  etc

# UpperDir はある
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/tmp/

# MergedDir はなくなる
$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/merged/
37b389953f47451e38e89dd37/merged/: No such file or directory

# WorkedDir もある
sudo tree /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
`-- work

1 directory, 0 files

コンテナを削除する

$docker rm 8c22dfe56161

# 全部消えた
sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/

$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/
ls: cannot access /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37-init/diff/: No such file or directory

$sudo ls /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/tmp/
ls: cannot access /var/lib/docker/overlay2/e2f33fb006d70d6849ea354aee5e984bd8d523f37b389953f47451e38e89dd37/diff/tmp/: No such file or directory

$sudo tree /var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
/var/lib/docker/overlay2/b3e38a747d4948bf34490d682d58a87b3eb0cc0ff52c50a6ec122fa2f8c9a38b/work/
`-- work

1 directory, 0 files


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

Dockerコンテナ内でGCPの証明書エラーと戦ってみた

Docker for Macで作成したコンテナ内にgcloudコマンドの環境を構築したところ、社内プロキシ関連の証明書でエラーが出たので回避策をまとめておきます

結論

gcloud config set auth/disable_ssl_validation True

で証明書のチェックを無効化する。

あるいは、ホストマシンにインストールされた証明書をコンテナ内に持って行って、以下のコマンドで証明書を指定する

gcloud config set core/custom_ca_certs_file /path/to/ca_certs

動作環境

macOS Mojave

version 10.14.5

$ docker --version
Docker version 18.09.2, build 6247962
$ code --version
1.35.1
c7d83e57cd18f18026a8162d042843bda1bcf21f
x64

事象

gcloud auth loginコマンドでログイン処理を行なったところ、以下のエラーが発生しました

ERROR: gcloud crashed (SSLHandshakeError): [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:727)

SSL: CERTIFICATE_VERIFY_FAILEDということで証明書のエラーとのことです。

対策方法

調べた感じ対策は2種類かな、という感じでした。

  1. gcloudコマンドのSSLのチェックを無効化する
  2. ホスト(Mac)にインストールされている証明書をコンテナ側にインストールする

この2つの方法を試してみました。

gcloudコマンドのSSLのチェックを無効化する

こちらは簡単で、コマンド1発で設定するだけです。

gcloud config set auth/disable_ssl_validation True

これでSSLのエラーが出ても無視するようになります。

ホスト(Mac)にインストールされている証明書をコンテナ側にインストールする

完全無視の方法は楽なんですがちゃんとした証明書でやる方法も欲しいということでやってみました。

プロキシ配下の場合にDockerコンテナ内でエラーが出るのは、プロキシのルート証明書がコンテナ内のOSにはインストールされていないからです。これによって、

  • ホストマシン(Mac)には社内プロキシ用の証明書がインストールされているので、ブラウザでみた場合は問題なし
  • コンテナや仮想マシンの場合は一般的な証明書しか入っていないのでエラーが出る

というような動きになります。

ということはホストマシンの証明書をコンテナ側にも設定してあげれば良い、ということになるのでやってみました
(逆に言うと、証明書が古いとかの原因でホスト側からもアクセスできないようなサイトの場合は無理なので、その場合は諦めます。)

手順はざっくり以下です。

  1. キーチェーン アプリからルート証明書のファイルをエクスポートする
  2. コンテナ内のLinuxに証明書のファイルをコピーする
  3. gcloudコマンドで証明書を指定する

細かい手順は次から

キーチェーンから証明書をエクスポートする

Macのキーチェーンアプリを開きます

以下のように、キーチェーンはシステム、分類は証明書を選ぶとインストールされている証明書の一覧が確認できます。

alt

この中から該当するルート証明書を選びます。
複数あってどれかわからないと言う場合は備考:ルート証明書の確認の方法で確認できます。

必要となる証明書を右クリックして***を書き出すというメニューからファイルに書き出します。

g_export.png

ファイル形式はpemとして、説明の為にファイル名はroot.pemとします。

このroot.pemができればホスト側の作業は終わりです。

試してみる

本当にちゃんと通信できるか試してみました。

まず、以下のDockerfileでgcloudコマンドがインストールされたUbuntuイメージを作成します。

こんな構成でファイルを配置して、docker-compose.ymlで立ち上げます。
root.pemは上記で書き出したファイルです。

./Dockerfile
./certificates
./certificates/root.pem
./docker-compose.yml
FROM ubuntu:18.04

RUN apt update && apt install -y lsb-release
RUN apt install -y curl gnupg
RUN export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)" && \
    echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \
    curl -k https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
    apt-get update -y && apt-get install google-cloud-sdk -y
docker-compose.yml
version: '3.3'

services:
  main:
    build: .
    tty: true
    volumes:
      - ./certificates:/certificates

docker-compose立ち上げて、コンテナに接続します

docker-compose up -d
docker-compose exec main bash

コンテナ内からgcloud auth loginで認証をしてみますが、まだ何も設定していないので当然ながらエラーが出ました。

$ gcloud auth login
Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?***********************

Enter verification code: 
ERROR: gcloud crashed (SSLHandshakeError): [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:727)

gcloud's default CA certificates failed to verify your connection, which can happen if you are behind a proxy or firewall.
To use a custom CA certificates file, please run the following command:
  gcloud config set core/custom_ca_certs_file /path/to/ca_certs

If you would like to report this issue, please run the following command:
  gcloud feedback

To check gcloud for common problems, please run the following command:
  gcloud info --run-diagnostics

gcloud setコマンドで証明書を指定する

エラーメッセージにもあるように、gcloud config set core/custom_ca_certs_file /path/to/ca_certsで証明書のファイル指定すれば良いということなのでやってみます。

証明書のマウント先は/certificates/root.pemになります

$ gcloud config set core/custom_ca_certs_file /certificates/root.pem 
Updated property [core/custom_ca_certs_file].

To take a quick anonymous survey, run:
  $ gcloud alpha survey

gcloud alpha surveyは何?と思いましたが、ただのアンケートのようなので無視します

この状態でもう一度ログイン処理を走らせます

$ gcloud auth login
Go to the following link in your browser:
    https://accounts.google.com/o/oauth2/auth?***********************

Enter verification code: 
WARNING: `gcloud auth login` no longer writes application default credentials.
If you need to use ADC, see:
  gcloud auth application-default --help

You are now logged in as [********].
Your current project is [None].  You can change this setting by running:

無事にログインできました。

この状態からプロジェクトを設定して、GCPのAPIなども叩けたので問題ないかなと思います。

備考:ルート証明書の確認

Webブラウザでサイトにアクセスすると、どの証明書で認証したかが確認できます。
ChromeでVisual Studio Marketplaceを開いた場合は以下のような感じです。

URLの左側の鍵をクリックするとこんなダイアログが出るので

g_export.png

証明書を選択すれば使われているルート証明書が確認できます。この中の一番上のものを選んでおけば大丈夫かと思います

g_export.png

おわりに

gcloudの証明書エラーと戦ってみました。
社内プロキシがあるとどうしても出てくる問題なので仕方ないような、無駄な時間のような...

ちなみに独自のルートCA証明書を追加する方法(Ubuntu, CentOS 7) | cloudpack.media の方法を使えばOS自体の証明書にも追加できるので、その他のツール周りでエラーが出る場合でもいけるはずです。

参考

Adding a custom CA Root certificate to GCloud utility (or Python generally) on Windows - Stack Overflow

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

【Docker】apt-getでffmpegのバージョンを指定してインストールする

やること

ubuntu 18.04のDockerイメージにバージョンを指定したffmpegをインストールします。

やり方

まず最低限のDockerfileが以下です。
ffmpeg=の後に指定しているのがバージョンです。

FROM ubuntu:18.04

RUN  apt-get update \
  && apt-get install -y ffmpeg=7:3.4.6-0ubuntu0.18.04.1 \
  && apt clean \
  && rm -rf /var/lib/apt/lists/*

CMD ["/bin/bash"]

この記事では、ffprobe-test:0.0.1と名付けてdocker buildした前提で話を進めます。

docker build -t ffprobe-test:0.0.1 .

指定可能なバージョン

ubuntu 18.04では以下のページのVersions publishedに示されているバージョンはそのままで指定することができます。

その他の内容を指定する場合は、デフォルトリポジトリに存在していないので、リポジトリを探して追加してやる必要があります。

インストールされたバージョンの確認方法

apt-cacheで確認できます。
Docker周りのコマンドについては省略します。

docker run --rm -i ffprobe-test:0.0.1 apt-cache policy ffmpeg
実行結果
$ docker run --rm -i ffprobe-test:0.0.1 apt-cache policy ffmpeg
ffmpeg:
  Installed: 7:3.4.6-0ubuntu0.18.04.1
  Candidate: 7:3.4.6-0ubuntu0.18.04.1
  Version table:
 *** 7:3.4.6-0ubuntu0.18.04.1 100
        100 /var/lib/dpkg/status

バージョンを7:3.4.2-2に変えてやると以下のような実行結果となります。

$ docker run --rm -i ffprobe-test:0.0.1 apt-cache policy ffmpeg
ffmpeg:
  Installed: 7:3.4.2-2
  Candidate: 7:3.4.2-2
  Version table:
 *** 7:3.4.2-2 100
        100 /var/lib/dpkg/status
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerを使ってAWS Lambdaのデプロイパッケージをビルドする(Python 3.7)

はじめに

https://aws.amazon.com/jp/lambda/
最近AWS Lambdaを使用する機会が増え、Python3.7のデプロイパッケージのビルド処理を汎用化したので共有します。

AWS Lambdaではライブラリなどを一つのzipファイルにまとめたものをパッケージとしてアップロードする必要があります。
Windowsで開発する場合、OSの違いからライブラリをそのままzipするだけだと動かない場合もあります。
そこで、Dockerを使ってLambdaの環境を再現したうえでパッケージを作成するという処理を実装してみました。

ソース

https://github.com/yusukey0720/lambda_packager_python
↑にいい感じにまとめてみたので参考にしてください。

使い方

※Dockerがインストールされていること。

requirements.txt

  • ここに必要なライブラリを記載。
./src/requirements.txt
numpy
pandas

lambda_function.py

  • ここに処理を記載する。
./src/lambda_function.py
def lambda_handler(event, context):
    # some functions

ビルドする

  • 下記のコマンドからビルド処理を実行する。
    • Dockerが立ち上がる
    • requirementsをインストール
    • ソースをzipする
    • distに出力される
sh build.sh

デプロイ

  • distに出力されたファイルをs3にアップロード
  • AWSコンソール画面からs3のパスを入力して保存

さいごに

やはりDockerは便利ですね。
s3のアップロードやzipの反映まで自動化できるとより便利になるなと感じました。
不明点等あればコメントください。

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

Dockerでホストのssh鍵をゲストOSと共有する際の注意点

まとめ

opensshのバージョン7.8以降で生成した鍵は後方互換性がない

経緯

Dockerコンテナ上でgithubからcloneを実行したかった。
SSH鍵をコンテナ毎に生成するのは現実的ではないので、
ホストOSのSSH鍵(github登録済)を使おうと思った

何が起きたか

docker-composeとDockerfileを記述して、
コンテナ上で鍵ファイルを閲覧できるところまでは確認。
任意のディレクトリでclone実行したところcloneに失敗

生成されたキーがおかしい?

ゲストOS上で直接ssh-keygenで生成したキーは使用できるか確認したところ特に問題なくcloneに成功。
ホスト上で作成した鍵がおかしい?と思ったが、ホスト上でもcloneコマンドは成功している。
両者のid_rsaをlessで確認したところ、下記の違いが確認された。

ホスト
-----BEGIN OPENSSH PRIVATE KEY-----
ゲスト
-----BEGIN RSA PRIVATE KEY-----

ムムム、ヘッダの内容が若干違う?

OpenSSHの確認

opensshのバージョンは、、、
ホスト

OpenSSH_7.9p1, LibreSSL 2.7.3

ゲスト

OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013

それっぽい違いがあるぞ、、、?!
調べたらすぐこんな記事が見つかりました。
https://dev.classmethod.jp/server-side/network/openssh78_potentially_incompatible_changes/
クラスメソッドさんありがとうございます!

openssh7.8以降を利用している際に後方互換性のあるキーを作成したい場合は-m PEMを付与する

ssh-keygen -m PEM

生成されたキーのヘッダを確認したところ旧バージョンの形式になってること確認
cloneも無事完了

ダイナミックな変更で驚いたが、オプションで解決できてよかったよかった。

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

Rails6の開発環境をDockerで構築しようとしたらドハマりした件

概要

Dockerでの開発環境構築に慣れていない私は、練習がてら公式の手順を元にRailsの開発環境を構築してみることに。
https://docs.docker.com/compose/rails/

その時ハマった事象と解決方法のメモ。

落とし穴

最近 Rails6がリリース されたということで、せっかくだから使ってみるかな!
→それが悲劇の始まりとは知る由もなく...

Your Ruby version is 2.6.3, but your Gemfile specified 2.6.0 問題

事象

Build the Project の手順でdocker-compose build した時に出たエラーメッセージ。

$ docker-compose build
db uses an image, skipping
Building web
Step 1/15 : FROM ruby:2.6
 ---> 8fe6e1f7b421
Step 2/15 : RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
 ---> Using cache
 ---> b487730f3d14
  :
(中略)
  :
Step 9/15 : RUN bundle install
 ---> Running in 3e945eba544e
Your Ruby version is 2.6.3, but your Gemfile specified 2.6.0
ERROR: Service 'web' failed to build: The command '/bin/sh -c bundle install' returned a non-zero code: 18

要するに、Gemfileで指定してるバージョンとアンタの環境のRubyバージョンが違ってまっせ、ということなんですが、これを解決するのにハマった。

解決プロセス

バージョン調査

バージョン違いまっせと言われているので、まずRubyのバージョンを確認するわけですが、この時にローカル環境のバージョンを確認したのが良くなかった。
コンテナ初級者あるある。

$ which ruby
/Users/username/.rbenv/shims/ruby

(デフォルトのパスではなく)rbenvで指定されたパスを指している。

$ ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-darwin18]

RubyのバージョンはGemfileの記述と同じく 2.6.0 である。

$ rbenv versions
  system
  2.3.0
  2.4.1
  2.5.1
  2.5.3
* 2.6.0 (set by /Users/username/Work/training/docker-begin/.ruby-version)

そもそもruby 2.6.3 はインストールすらされていない!
なんでだ!キーッ!!となったわけですが、、

そういや、コンテナに環境作るんだからローカルのインストール状況関係ないよね?

と思い直したのでした。

解決方法

DockerfileのFROM句では、マイナーバージョンを明示しない限り最新版が指定されるらしい。
例えば FROM ruby:2.6 とすると、その時最新バージョンである 2.6.3 と認識される模様。
:point_right: ソースは自身の試行錯誤

Dockerfileを確認するとまさに 2.6 としていたため、下記のように明示してやることで無事 docker-compose build 出来たのでした。

FROM ruby:2.6.0

rails server 立ち上がってない問題

事象

無事手順を終えウェルカムページが見れる状態になったハズなのですが、どういう訳か localhost:3000 にアクセス出来ない。

localhost 2019-08-20 19-21-39.png

コンテナは問題なく立ち上がっているはずなのに...

$ docker-compose ps
       Name                     Command               State           Ports         
------------------------------------------------------------------------------------
docker-begin_db_1    docker-entrypoint.sh postgres    Up      5432/tcp              
docker-begin_web_1   entrypoint.sh bash -c rm - ...   Up      0.0.0.0:3000->3000/tcp

なぜだ。

解決プロセス

docker logsしてみる

こんな時には docker logs するといいよ、とどこかの誰が言っていたのでやってみる。

$ docker logs docker-begin_web_1
=> Booting Puma
=> Rails 6.0.0 application starting in development 
=> Run `rails server --help` for more startup options
RAILS_ENV=development environment is not defined in config/webpacker.yml, falling back to production environment
Exiting
/usr/local/bundle/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:91:in `rescue in load': Webpacker configuration file not found /myapp/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /myapp/config/webpacker.yml (RuntimeError)
        from /usr/local/bundle/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:87:in `load'
        from /usr/local/bundle/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:84:in `data'
        from /usr/local/bundle/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:80:in `fetch'
        from /usr/local/bundle/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:39:in `public_path'
        from /usr/local/bundle/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:43:in `public_output_path'
        from /usr/local/bundle/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:47:in `public_manifest_path'
        from /usr/local/bundle/gems/webpacker-4.0.7/lib/webpacker/manifest.rb:83:in `load'
  :
(中略)
  :

あれ、rails serverが立ち上がってない...
開発環境に config/webpacker.yml が定義されていない??

Webpackerをインストール

どうやら、Rails6 ではWebpacker がデフォルトで導入されるようになったらしい。

てことは、Webpackerをインストールしてやらないとrails serverも立ち上がらないということなのかな?

ということで、Webpackerをインストールするために必要なyarnであったりNode.jsであったりをインストールするぞ!という命令をDockerfileに書いてやる。

FROM ruby:2.6.0
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
########################################################################
# yarnパッケージ管理ツールをインストール
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn
# Node.jsをインストール
RUN curl -sL https://deb.nodesource.com/setup_7.x | bash - && \
apt-get install nodejs
#######################################################################
  :
(中略)
  :

そしてWebpackerをインストール。

$ docker-compose run web bundle exec rails webpacker:install
Starting docker-begin_db_1 ... done
RAILS_ENV=development environment is not defined in config/webpacker.yml, falling back to production environment
      create  config/webpacker.yml
Copying webpack core config
      create  config/webpack
      create  config/webpack/development.js
      create  config/webpack/environment.js
      create  config/webpack/production.js
      create  config/webpack/test.js
  :
(中略)
  :
info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.
Webpacker successfully installed ? ?

問題なくインストール出来たのでもう一度コンテナを起動!

Ruby on Rails 2019-08-20 19-20-06.png

無事スタートラインに立つことが出来たのでした:clap:

※その後、ついでにRubyのバージョンを 2.6.3 に上げてもう一度同様の手順を試しました。

参考

Rails(Docker)でwebpackがインストールできない

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