- 投稿日:2020-08-08T21:48:52+09:00
CircleCIでdockerイメージをbuild & pushする
はじめに
githubにてmasterブランチにmergeされたときに、GCPのContainer Registryにimageをpushする
CircleCIセットアップ
- CIの実行ファイルを作成
- CircleCIの管理画面でプロジェクト追加
1. CIの実行ファイルを作成
ルート直下に.circleciのフォルダを作成して、その中にconfig.ymlのファイルを作成する
(いったん、hello worldするだけ実行ファイル)version: 2.1 jobs: build: docker: - image: circleci/ruby:2.6.5 steps: - checkout - run: echo "hello world"2. CircleCIの管理画面でプロジェクト追加
CircleCIのサイトからgithubログインして対象のリポジトリを追加して完了
そして、hello world確認!config.ymlにdockerイメージビルドする処理を書く
- Gcloud連携
- dockerイメージをbuild & push
- masterブランチへmergeされた時だけ実行する
1. Gcloud連携
公式ドキュメントを参考に進める
https://circleci.com/docs/ja/2.0/google-auth/ciの実行環境にgcloudのsdkを加える
executors: docker: - image: google/cloud-sdkGoogle Cloud SDK のツールを使用する前に、gcloud を承認する必要があるので、下記手順にしたがってサービスアカウントを作成する
https://cloud.google.com/sdk/docs/authorizing#authorizing_with_a_service_accountCircleCI にキーファイルをプロジェクト環境変数として追加する
https://circleci.com/docs/ja/2.0/env-vars/#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E5%86%85%E3%81%A7%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8Bgcloudを使用してGoogle Cloud SDKを承認する
また、GCRにpushするのでその認証もするversion: 2.1 jobs: create_image: docker: - image: google/cloud-sdk steps: - run: name: Gcloud Config command: | echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account --key-file=- gcloud --quiet config set project ${GOOGLE_PROJECT_ID} gcloud --quiet config set compute/zone ${GOOGLE_COMPUTE_ZONE} - run: name: GCloud Auth configure-docker command: | gcloud auth configure-docker --quiet --project ${GOOGLE_PROJECT_ID} #(workflowsは省略)実行してみると、承認できていることが確認できた!
2. dockerイメージをbuild & push
まずは、CI環境でdockerを使えるようにする
なんとsetup_remote_dockerを追加するだけで完了!version: 2.1 jobs: create_image: docker: - image: google/cloud-sdk steps: - run: name: Gcloud Config command: | echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account --key-file=- gcloud --quiet config set project ${GOOGLE_PROJECT_ID} gcloud --quiet config set compute/zone ${GOOGLE_COMPUTE_ZONE} - run: name: GCloud Auth configure-docker command: | gcloud auth configure-docker --quiet --project ${GOOGLE_PROJECT_ID} - setup_remote_docker #(workflowsは省略)https://circleci.com/docs/ja/2.0/building-docker-images/
次に、checkoutしてからdockerイメージをbuild & pushする
version: 2.1 jobs: create_image: docker: - image: google/cloud-sdk steps: - run: name: Gcloud Config command: | echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account --key-file=- gcloud --quiet config set project ${GOOGLE_PROJECT_ID} gcloud --quiet config set compute/zone ${GOOGLE_COMPUTE_ZONE} - run: name: GCloud Auth configure-docker command: | gcloud auth configure-docker --quiet --project ${GOOGLE_PROJECT_ID} - setup_remote_docker - checkout - run: name: Docker Build command: | docker build . -t gcr.io/${GOOGLE_PROJECT_ID}/gcp-rails_sports-rails_backend:${CIRCLE_SHA1} - run: name: Docker Push command: | docker push gcr.io/${GOOGLE_PROJECT_ID}/gcp-rails_sports-rails_backend:${CIRCLE_SHA1} #(workflowsは省略)build & push できていることを確認!
3. masterブランチへmergeされた時だけ実行する
最後にmasterのときだけcreate_imageのジョブを実行するようにfilterを追加して完成!?
version: 2.1 jobs: create_image: docker: - image: google/cloud-sdk steps: - run: name: Gcloud Config command: | echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account --key-file=- gcloud --quiet config set project ${GOOGLE_PROJECT_ID} gcloud --quiet config set compute/zone ${GOOGLE_COMPUTE_ZONE} - run: name: GCloud Auth configure-docker command: | gcloud auth configure-docker --quiet --project ${GOOGLE_PROJECT_ID} - setup_remote_docker - checkout - run: name: Docker Build command: | docker build . -t gcr.io/${GOOGLE_PROJECT_ID}/#{任意のイメージ名}:${CIRCLE_SHA1} - run: name: Docker Push command: | docker push gcr.io/${GOOGLE_PROJECT_ID}/#{任意のイメージ名}:${CIRCLE_SHA1} workflows: build: jobs: - create_image: filters: branches: only: master
- 投稿日:2020-08-08T19:54:07+09:00
docker-composeでのvolume作成方法
概要
dockerでのvolumeの作成方法に手こずったので、備忘録です。
よくあるvolume作成方法
docker-compose.ymlversion: "3" services: db: image: mysql volumes: - ./db/mysql/volumes:/var/lib/mysqlこの記述のみでは
そのコンテナ自体にvolumeが作成され、データを保存
を行うことはできるがデータの永続化はできない。
理由は、コンテナが削除されると一緒にデータも削除されてしまうため。データを永続化するには
docker-compose.ymlversion: "3" services: mysql: image: mysql volumes: - mysql-db:/var/lib/mysql volumes: mysql-db: driver: localこれが正しい記述となる。
やっていること
- mysqlコンテナにデータを格納するvolumeを作成
- そのvolumeを
「データを永続化するためだけの役割」
であるvolumeコンテナとマウント実際にvolumeを確認
まず
docker-compose.yml
の設定を反映させる&サーバー起動$ docker-compose up --buildその後、volumeの一覧を表示してみると
$ docker volume ls DRIVER VOLUME NAME local b1d0c166382335a52c546e1ea2eaddf752d6f410c4c6664bdc59e9606f4bd25 local myapp_mysql-db新たにvolumeが作成できていることを確認できるはずです。
参考にした記事
- 投稿日:2020-08-08T19:42:05+09:00
Herokuで動かす仮想ブラウジング環境
この記事について
Heroku Container Registry & RuntimeとnoVNCで、日本語入力可能な一時的なブラウジング環境を作って使う話。
恐らくもう散々同じことが成された領域だと考えられるが、アウトプットとして残しておこうと思う。今回の記事ではブラウジングに限定しているが、制限はありつつ普通にターミナルやWindowManagerも動くので、ちょっとした用途に色々使うことができる。
余談だが、IBM Cloudの無料Liteアカウントで使えるCloud Foundryではdiego_dockerが有効なので、同じことができるか試してみた。結果としては、メモリやディスクの制限が厳しすぎて無理だった。もっと技量があればいろいろ削ったりして、いけるのかもしれない。
背景
様々な事情により、「今すぐ使える仮想デスクトップというか、ブラウザだけ動く環境でいいから、ちょっとだけ欲しい」という感覚になることはないだろうか。
そこで皆大好きHerokuである。誰でも一度は何らかをデプロイして個人で使ったことがあるのではないだろうか。今回はHerokuに、デスクトップというかブラウジング環境をデプロイして使ってみたい。
用語説明
Heroku Container Registry & Runtime
Heroku Container Registry & RuntimeはHerokuでDockerベースのアプリケーションを動かす仕組みで、割と前の2017年10月くらいにGAになったもの。
Dockerfile
を書いてheroku container:push
とheroku container:release
することでアプリケーションをデプロイできる。イメージに特定のタグをつけてdocker push
でも可能。なお、コンテナ内でのアプリケーション実行ユーザはuXXXXXで、コンテナ内部のファイルの所有者も/etc/shadowだとか一部を除いてuXXXXXのユーザになる。
noVNC
noVNCは、ブラウザをクライアントにしてVNCを使うことができるもの。HTML5を使って作られていて、通信はWebSocketで行われ、websockifyで後ろにたっているVNCサーバとの仲介をする。
クライアントはブラウザさえあればいい、というのが簡単で良い。
今回つくったもの
上記のHeroku Container Registry & RuntimeでnoVNCとブラウザの入ったコンテナを入れて動かした。ソースはここ (https://github.com/qb0C80aE/ghostship) で、Herokuのアカウントを持っていてDockerとHeroku CLIがあれば、恐らく10分もかからずデプロイできる。
構成物は簡単な
Dockerfile
、エントリポイントにするシェルスクリプト、あとは後述する日本語を打つための設定をあらかじめいれた.config
ディレクトリだけである。また、
README.md
にも書いたとおり、偉大なるGitHub ActionsはDockerとHeroku CLIをサポートしているため、GitHubのアカウントを持っていればローカルにDockerとHeroku CLIをインストールする必要もなかったりする。このスクリーンショットでは、外枠のブラウザがローカルで、内側のブラウザはHeroku上のものをVNCで操作しているものである。
偉大なプラットフォームとソフトウェア
正直、このリポジトリではすごい事はなにひとつしていない。
すごいのはこれを実現してくれるHerokuとソフトウェア群である。HerokuもnoVNCも本当にすごい。いつもお世話になっているし、足を向けて寝ることは決して出来ない。
なお、特に何かにログインとかせずに外とデータの受け渡しがしたいときは、piping-serverという偉大なOSSを使ったりすることで実現できる。
ちょっとした工夫
ところで、皆大好きHerokuのfree dynoは、執筆時点ではたしか30分アクセスがない状態が続くと自動的にダウンする仕様になっている。
dynoのログを見るとわかるが、noVNCで繋いでいる間は、reconnect&autoconnectしていても、再接続時にHTTPアクセスがあったという動きにはならない。
このままでは環境の利用中にdynoがダウンするため、noVNCのvnc.html
にすこし工夫をして、KeepAliveをいれている。具体的には、
Dockerfile
に以下のような適当なパッチをいれた。... sed -i "s/<\/head>/ <script>\n var skeepalive = function() {fetch(window.location.protocol + '\/\/' + window.location.host, {cache: 'no-cache'});};\n setInterval(skeepalive, 300000);\n <\/script>\n<\/head>/g" /opt/noVNC-master/vnc.html && \ sed -i "s/<\/head>/ <script>\n var skeepalive = function() {fetch(window.location.protocol + '\/\/' + window.location.host, {cache: 'no-cache'});};\n setInterval(skeepalive, 300000);\n <\/script>\n<\/head>/g" /opt/noVNC-master/vnc_lite.html && \ ...これで、環境をブラウザで開いている間だけ、このdynoは生きることができる。
そして元々の仕様のとおり、ブラウザを閉じてしばらく経過するとダウンする。欲しい間だけ環境に生きていてほしいので、このように勝手にダウンしてくれるのは逆に都合が良かったりもするが、それとは別にいつも助けてもらっているHerokuにはお布施を奉納することにする。
なお仕様上、一日一回dynoが再起動するのは運命なのでしかたない。一時的なブラウジング環境なので、割り切りが重要であり、この環境では決して重要な仕事をしないことが肝心である。
日本語変換
ややもすると、検索では日本語を打ちたくなるので、日本語変換ができてほしい。
そこで、fcitxをいれて、Ctrl+Space
で日本語変換ができるようにした。
技量が足りずmozcを動かすことができなかったので、anthyを使うことにした。制限
TwitterはEC2のIPアドレスを弾いているのか、閲覧不能になることが大半である。どこかのproxyを設定するなりすれば閲覧可能になるので、どうしてもこの上でTwitterが見たい人は設定してみてほしい。
なお、スレッド数上限が256とか色々制限があるので、沢山タブを開きすぎたり、色々な条件でダウンすることもよくあるが、気にしないことにする。
- 投稿日:2020-08-08T17:30:04+09:00
Laravel×Docker×Dusk×Seleniumでのテスト実行
はじめに
インターン現場でLaravelを使用しており、テスト環境の構築を行いました。
テストツールとしてDuskを使用し、seleniumとの連携という構成をとり、導入で何度かつまづいたので自分メモとして残したいと思います。
Duskって?
-ドキュメント
Laravelが標準で用意している、ブラウザの自動操作によるテストAPI。
テスト中はブラウザが勝手に動くのを眺めながらのんびりできます(笑)Duskは「$php artisan dusk:install」でコマンドインストール後、すぐに使えます。
しかし今回は現場の意向でデフォルトのChromeDriverの使用ではなくseleniumを使用することになりました。目標
--開発環境---
- Laravel 6.18.26
- Docker(Docker-compose) 19.03.8
docker環境でDusk × seleniumでテストを実行することを目標とします。
開発環境でdockerを使用していたので、selenium用のコンテナを準備するところからはじめました。以下、順にまとめていきます
1.seleniumのコンテナを準備
selenium用のコンテナを定義するために、docker-compose.ymlに以下を追記。
docker-compose.ymlselenium: image: selenium/standalone-chrome-debug ports: - 4444:4444 - 5900:5900 container_name: selenium-container depends_on: - nginx privileged: trueポートを2つ開放してますが、
4444 ⇨ selenium serverのポート
5900 ⇨ VNCのポートです。
[参考]VNCについて2.コンテナ起動
terminal$ docker-compose up ... Creating mysql-container ... done Creating phpmyadmin-container ... done Creating php-fpm-container ... done Creating nginx-container ... done Creating selenium-container ... doneseleniumのコンテナが無事立ち上がりました。
php-fpmのコンテナ中に入ります。terminal$ docker exec -it php-fpm-container bash3.Duskのインストール
ほぼ公式の引用です。
以下のコマンドはコンテナ中で行ってください!terminal(コンテナ内)# 共存パッケージのインストール $ composer require --dev laravel/dusk # dusk install $ php artisan dusk:installdockerを起動するとselenium portとVNCポートが開放されます。
4.seleniumの接続(:4444)
デフォルトのChromeDriveではなくseleniumを使用する場合、tests/DuskTestCase.phpを書き換える必要があります。
DuskTastCase.php#driverメソッドを以下に書き換え protected function driver() { return RemoteWebDriver::create( 'http://selenium:4444/wd/hub', DesiredCapabilities::chrome() ); }ここで、docker-compose.ymlで定義した4444portが登場します!
5.VNCの接続(:5900)
今度はVNCに接続を行います。
macのfinderからlocalhost:5900に接続します。↓dockerが起動していればこんな感じでseleniumの画面が表示されました!!
6.テストの実行
以下の簡単なログインテストを実行してみました。
LoginTest.php<?php namespace Tests\Browser; use Illuminate\Foundation\Testing\DatabaseMigrations; use Laravel\Dusk\Browser; use Tests\DuskTestCase; class LoginTest extends DuskTestCase { /** * A Dusk test example. * * @return void */ public function test_02_PassReset(){ // login test $this->browse(function (Browser $browser) { // ページ"/login"で文字列"LARAVEL"を確認 $browser->visit('login') ->assertSee('LARAVEL'); }); } }こちらのテストを実行。
↑テスト実行時のキャプチャです。きちんとテストブラウザが動いて/loginにアクセスできています!
terminal$ php artisan dusk PHPUnit 8.5.8 by Sebastian Bergmann and contributors. .. 2 / 2 (100%) Time: 4.4 seconds, Memory: 18.00 MB OK (2 tests, 2 assertions)テスト結果も◎でした!!!
まとめ
ブラウザテスト自体が初めてだったので、単純に楽しかったです!
時間があればselenium関連でスクレイピングとかにも挑戦したい!!!※誤りや質問等ございましたらコメント頂けますと幸いです。
- 投稿日:2020-08-08T17:09:55+09:00
Dockerで作る、環境整備 (PythonでのGrADSの後処理をしたい
何をしたいのか?
- PythonでGrADS用のファイルを読み込んで後処理をしたい
- しかし共有計算資源の環境はクリーンでなければならない
- だがしかし、変換ソフト、ライブラリなどなどインストールしたいものがいっぱいある
ということで、コンテナ仮想化を使おうということです。
Docker
Dockerを使うと何がいいかというと、計算資源を汚すことなく、必要な後処理を行う専用の仮想計算機を作り上げることができます。使うときにコンテナを立ち上げ、処理を行った後は破棄してまた必要になったら立ち上げることができます。
Dockerの場合は立ち上げのコストが非常に低いので、気軽に立ち上げて一つの処理をした後また破棄することが気軽にできます。環境整備手順
Dockerfileを書くと自動化できていいのですが、ここでは単にシェルを立ち上げて整備して、それを単純にコミットしてイメージを作ることにします。
長期的に使いたいなら、バージョンアップも可能になるようにDockerfileを作るべきですが、最初の基本の機能の確認はシェルで行ったほうが理解が深まります。今回はUbuntuをもとに、cdoとpip3, netcdf4をインストールします。
1. もとになるイメージをpull(拾ってくる)して走らせる
今回はUbuntuを使います。
$ docker pull ubuntu/ubuntu
$ docker images
で、イメージが作れたことが確認できます。
イメージを走らせるためには、
$ docker run -it ubuntu/ubuntuとします。
2. 必要なソフトウェアのインストール
pip3
とcdo
をインストールします。
pip3
でnetCDF4
もインストールします。# apt update # apt install python3 python3-pip cdo # pip3 install netCDF43. 動作確認
きちんとcdoで変換できてnetCDF4もインポートできるか確認します。
# python3 >>> import netCDF4 as nc >>> ^D # cdo ....4. コミットしてimageを作成する
exitコマンドかCtrl+dで抜けて、イメージを作りましょう。
イメージを作るために必要なコンテナIDは、終了したコンテナを確認するために-a
が必要です。# exit (host) $ docker ps -aこのような画面になると思います。
CONTAINER IDはコミットの時に指定するコンテナIDになります。
IMAGEのところにimageの名前があって、STATUSのところでexited ** agoとなっているので、大体どれかはそこを見ればわかると思います。
$ docker commit [container id] [author]/[image名]というようにコミットしてあげましょう。
$ docker images
で、イメージが作れたことが確認できます。
5. 実際に計算させてみる
実際に計算させるとき、2通りあって、runしてからインタラクティブにシェルから実行することもできます。ただ、今回はrunの際にコマンドを指定して実行させてみます。
プログラム、データ群のディレクトリをDockerへとバインドすることで、実際にコンテナから容易にアクセスることができます。また、グラフの確認にXフォワーディングをします。
$ sudo docker run -e DISPLAY=$DISPLAY --net host -v /tmp/.X11-unix:/tmp/.X11-unix -v $HOME/.Xauthority:/root/.Xauthority -v /home/xxx/:/home/ --shm-size 16g xxx/ubuntu-cdo2 /bin/bash -c "cd /home/speedy-epyc/speedy/python-script; python3 rmse.py"
--shm-size
は、足りなくなるプログラムがあれば必要に応じてつけてください。
- 投稿日:2020-08-08T16:59:40+09:00
dockerコマンド実行時に出たエラー
dockerのimageを作成しようとしたら以下のエラー発生
$ docker-compose build
ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running?
If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.ググって見つけた記事には権限を変更しろとあるので以下を実行(ec2等の場合はexitしてから再起動)
$ sudo usermod -aG docker $USER
$ sudo chmod +x /usr/local/bin/docker-composeしかし、エラーは変化せず。。。
試しに以下のコマンドを実行するとrunningになっていなかった。
$ sudo service docker status
dockerをスタートさせたら無事にコマンドが通るようになった。
$ sudo service docker start
エラー出たらまずstatus確認するの大事ですね!
- 投稿日:2020-08-08T16:44:57+09:00
docker-compose upでDBが立ち上がらない「Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)」への対処法
dockerで環境構築をし、サーバーを起動しようと
docker-compose up
をすると
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)
というエラーが出てしまう。ターミナルにて、エラーログを確認すると
何かが原因でDBがシャットダウンしてしまっている模様。
privilege tables
なのでsudoで作成するユーザのテーブル?
なぜdockerでこの内容のエラーが出る?
と色々疑問に思ったが、とりあえず一度全てのvolumeを削除してみることに。解決策
①volumeのIDを調べる
$ docker volume ls DRIVER VOLUME NAME local b1d0c8467782387a61c446e1ea2aedaa745d6f120c4c6423bdc37e9005a7bd34②上記で調べた
VOLUME NAME
を用い、rmコマンドにてvolumeを削除$ docker volume rm [VOLUME NAME] # 例↓ $ docker volume rm b1d0c8467782387a61c446e1ea2aedaa745d6f120c4c6423bdc37e9005a7bd34③
docker-compose.yml
を元に、コンテナ&サーバー再起動$ docker-compose up --build $ docker-compose run web rails db:create $ docker-compose run web rails db:migrate④localhost:3000にアクセス
→ 無事エラーなく起動原因
mysqlのテーブル情報が保存される場所がvolumeなので
コンテナを削除した際にvolumeコンテナを削除しきれておらず、前回のmysqlの情報が中途半端に残っていたため
、権限不足となっていたみたいです。これ以前に何回もコンテナを作って削除して、を繰り返して試行錯誤していたため、その時の残骸でしょう...
参考にした記事
- 投稿日:2020-08-08T16:44:57+09:00
docker-compose upでDBが立ち上がらないときにやったこと
dockerで環境構築をし、サーバーを起動しようと
docker-compose up
をすると
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)
というエラーが出てしまう。ターミナルにて、エラーログを確認すると
何かが原因でDBがシャットダウンしてしまっている模様。
privilege tables
なのでsudoで作成するユーザのテーブル?
なぜdockerでこの内容のエラーが出る?
と色々疑問に思ったが、とりあえず一度全てのvolumeを削除してみることに。解決策
①volumeのIDを調べる
$ docker volume ls DRIVER VOLUME NAME local b1d0c8467782387a61c446e1ea2aedaa745d6f120c4c6423bdc37e9005a7bd34②上記で調べた
VOLUME NAME
を用い、rmコマンドにてvolumeを削除$ docker volume rm [VOLUME NAME] # 例↓ $ docker volume rm b1d0c8467782387a61c446e1ea2aedaa745d6f120c4c6423bdc37e9005a7bd34③
docker-compose.yml
を元に、コンテナ&サーバー再起動$ docker-compose up --build $ docker-compose run web rails db:create $ docker-compose run web rails db:migrate④localhost:3000にアクセス
→ 無事エラーなく起動原因
mysqlのテーブル情報が保存される場所がvolumeなので
コンテナを削除した際にvolumeコンテナを削除しきれておらず、前回のmysqlの情報が中途半端に残っていたため
、権限不足となっていたみたいです。これ以前に何回もコンテナを作って削除して、を繰り返して試行錯誤していたため、その時の残骸でしょう...
参考にした記事
- 投稿日:2020-08-08T16:23:53+09:00
Docker + Rails6 + Postgresql の開発環境を構築する
前提
Rails環境を構築していないチームメンバーも環境構築に手間をかけずにローカルで簡単にプロジェクトを動かせるようにとDockerを導入しました。私自身はローカルにRails環境を構築しているため、プロジェクト作成はローカルで行い、Dockerとローカル直のいずれも動作できるようにしました。
Dockerはすでにインストールされているものとします。環境
- macOS Catalina 10.15.4
- Ruby 2.7.1
- Rails 6.0.3.2
- PostgreSQL 12.3
- Docker version 19.03.12
プロジェクト新規作成
$ mkdir myapp; cd $_ $ rails new . --skip-coffee --skip-turbolinks --database=postgresql環境変数を管理するdotenv-railsを導入
環境変数によって、Dockerで動かすかローカル直で動かすか選べるようにします。
Gemfilegem 'dotenv-rails'gemをインストール
$ bundle install下記はDockeで動かす場合の環境変数の設定例です。
.envDATABASE_HOST=db DATABASE_USER=postgres DATABASE_PASSWORD=secretローカル直で動かす場合は
DATABASE_HOST=localhost
とします。Docker用ファイル作成・編集
docker-compose.ymlversion: '3' services: db: image: postgres volumes: - ./tmp/db:/var/lib/postgresql/data ports: - "5433:5432" environment: POSTGRES_USER: 'postgres' POSTGRES_PASSWORD: 'secret' POSTGRES_DB: 'db' webpacker: build: . command: bundle exec bin/webpack-dev-server volumes: - .:/myapp ports: - "8080:8080" web: build: . command: /bin/sh -c "rm -f /myapp/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000" depends_on: - db - webpackerdockerfileFROM ruby:2.7.1 ENV LANG C.UTF-8 # 必要なライブラリをインストール RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs # 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 # ワークディレクトリ設定 RUN mkdir /myapp WORKDIR /myapp ADD Gemfile /myapp/Gemfile ADD Gemfile.lock /myapp/Gemfile.lock RUN bundle install COPY . /myapp EXPOSE 3000
database.yml
にhost
、username
、passwrd
の設定を追加/config/database.yml: 省略 default: &default adapter: postgresql encoding: unicode host: <%= ENV.fetch("DATABASE_HOST") { "127.0.0.1" } %> # 追記 username: <%= ENV.fetch("DATABASE_USER") { "postgres" } %> # 追記 password: <%= ENV.fetch("DATABASE_PASSWORD") { "" } %> # 追記 # For details on connection pooling, see Rails configuration guide # https://guides.rubyonrails.org/configuring.html#database-pooling pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> : 省略image構築
$ docker-compose buildパッケージインストール
$ docker-compose run --rm web bin/yarn installデータベース作成
$ docker-compose run --rm web rails db:create起動
$ docker-compose uphttp://localhost:3000/ へアクセスできます。
ローカル直で動かす場合
.env
を編集し、yarn install
、rails db:create
、rails s
で起動します。
- 投稿日:2020-08-08T13:50:43+09:00
転職活動のためのデータ取得コード - Linkedin編
はじめに
こんにちは、今日はLinkedinのAPIを使用することで、友達の友達の友達までのプロフィール情報を取得するコードを紹介したいと思います。
このコードを使用することで、気になるあの企業では、どのくらいの人が退職しているのか、退職した人はどんな人なのか、平均勤続年数、転職先はどういう企業が多いのかを定量的に分析するためのデータが取得できます。(特にベンチャー企業とかはなかなか内部の情報が分からないのでベンチャー転職の役に立つ予感がしています。)
しかも、LinkedinのAPIは自身のアカウントさえ持っていれば、基本的には何の登録も必要とせず叩けるので、お手軽に試すことができます。
ただし、以下の注意点があります。
- 友人検索は無料アカウントだと、回数制限があるので無駄に検索しないことをおススメします。有料アカウントになればいくらでも検索かけられます
- 友達数が少ないと、気になる企業の関係者の情報が取得できない可能性が高いです。その場合はエージェントとか業界のリーダーみたいな人と繋がると良きかと思います。
では、早速友達の友達の友達のプロフィール情報を取得するコードを作っていきたいと思います。
今回は、docker上で動くように作成したので、多くの人の環境で動くものになっています。
是非動かせるところまで作ってみて、転職活動のための情報収集に役立てて頂ければ嬉しいです。一応docker初心者の方にもわかる形で記載しているので、dockerの勉強にもなるかもしれません。
フォルダ構成
ローカル環境に適当にlinkedinみたいなフォルダを作成して、以下のフォルダ構成を作成してもらえればと思います。
(余談ですが、フォルダ構成を書く際はこの記事が役に立ちます)linkedin/ ├ input/ ├ company.csv ├ output/ ├ script/ ├ api.py ├ .dockerignore ├ docker-compose.yml ├ Dockerfile
- input: 調査したい企業名を入力したcsvファイルを入れておきます。csvファイルは以下のような形式で作成します。
- 会社名というカラムに対して、その下に気になる企業を色々入れることができます。
会社名 Preferred Networks PKSHA Technology
- output: 調査したい企業に関係している方のプロフィール情報がjson形式で出力されます。
- script: linkedinからデータを引っ張ってきて、outputにデータを格納するコードが記載されています。
dockerの設定
dockerをご存知ない方は以下のサイトとか見てみてください。簡単に言うと、PC内に仮想環境をお手軽に作ることができ、その仮想環境でごちゃごちゃやって、仮想環境をぶっ壊しても問題ないよという技術です。
- Dockerでデータ分析環境を手軽に作る方法dockerとdocker-composeをインストールしていない方は、window系とmacとかlinuc系はインストール方法が異なるので、適切なインストール方法を行ってください。
今回は、docker-composeを使うことで、linkedinのフォルダに移動して、以下のコマンドを打ち込めば、お手軽にデータ取得ができるようにdockerの設定を行います。
docker-compose upDockerFile
以下のような内容をファイルの中に記述していきます。
- どういうイメージを使ってインストールするのか
- どんなライブラリを追加で入れておくのか
- イメージにローカル環境のどんなファイルを持ってくるのか
- dockerの起動と共にどのpythonファイルを実行するのか今回はanaconda環境の上にlinkedinのAPIとかを追加でインストールします。
linkedinのAPIにはこのリポジトリが一番使いやすそうだったので、こちらをもとにコードを作成します。docker.compose.yml# anacondaの開発環境をベースにする FROM continuumio/anaconda3:latest # ライブラリの追加インストール RUN pip install -U pip && \ pip install linkedin-api~=2.0.0a # docker環境内でフォルダ移動を行い、ローカルファイルを移動先のフォルダにコピーする WORKDIR /tmp/working COPY ./ ./ # api.pyを実行する CMD ["python", "-u", "./script/api.py"]docker-compose.yml
お手軽実行できるようにするために、docker-compose.ymlを作成していきます。
このファイル内では、マウントするディレクトリがどこかも記載します。
(マウントによってdocker上の特定のフォルダとローカル上の特定のフォルダを同期することができます。これによりdocker上で作成したファイルをローカル環境で取得できるようになります。)docker-compose.ymlversion: "3" services: app: build: . # ローカル環境の現在のディレクトリとdocker環境上の/tmp/workingを同期する volumes: - ./:/tmp/working.dockerignore
このファイルはさほど重要ではないのですが、Dockerfileをビルドする際に除去するファイルを記述でき、重いファイルで不必要なものを入れているとビルドが遅くなるそうなので、outputとかinputとかを中に記述します。
input output script上記の操作でdocker関係の設定は終了です。
後は、api.pyを記述し、実際にデータを持ってくる処理を書きます。データ取得処理
特段難しいことを行っているわけではないのですが、基本的には以下の処理を行っていきます。
- inputフォルダにある企業リストのcsvファイルを読み込んでくる
- 企業リストをもとにlinkedinから関係者のデータを取得してくる
- outputフォルダに関係者のプロフィール情報をjson形式で吐き出す
linkedinAPIの認証だけお忘れなくいただければと思います。
api.py# coding: utf-8 import os import json import logging import pandas as pd from linkedin_api import Linkedin def main(): # get company list df_company = pd.read_csv('./input/company.csv') # Authenticate using any Linkedin account credentials api = Linkedin('linkedinに登録しているメールアドレス', 'linkedinのログインパスワード') for company_name in df_company['会社名']: # retry processing for _ in range(3): try: logging.info(f'start to {company_name}') person_ids = get_people_ids(api, company_name) logging.info(f'number of person_id :{len(person_ids)}') profiles = list(get_person_profile(api, person_ids)) output_profile_data(company_name, profiles) logging.info(f'success to output') except: logging.info(f'retry to {company_name} :{_}_times') else: break def get_people_ids(api, company): '''get people ids in a company ''' network_depth_list = ['F', 'S', 'O'] results = [] for network_depth in network_depth_list: result = api.search_people( keywords=company, network_depth=network_depth ) results.extend(result) return results def get_person_profile(api, ids): '''get person profile information about career ''' for person_id in ids: profile = api.get_profile(person_id['public_id']) yield profile def output_profile_data(company, data): '''output profile data to output folder ''' os.makedirs(f'./output/{company}', exist_ok=True) for d in data: name = d['lastName'] + d['firstName'] with open(f'./output/{company}/{name}.json', 'w') as f: json.dump(d, f, indent=4) if __name__ == '__main__': main()これで準備は完了です。
では、早速実行してみましょう。実行
ターミナルかコマンドプロンプト上でlinkedinフォルダに移動し、以下のコマンドを打って下さい。
このコマンドを打つことで、docker-compose.ymlの中身を読み取って、dockerを起動してくれます。docker-compose upすると、実行にそこそこ時間がかかりますが、データの取得が開始されるかと思います。
僕は少し異なる設定でやっているのですが、以下のような結果が出てきました。person_idは該当者数を表しています。
データを取得後は、お好きなようにデータを調理するだけです。ここの調理方法は色々あると思いますが、私がどんな分析をしたのか別記事で紹介しようかなと考えています。
まとめ
この記事では、docker環境上でLinkedinのAPIを叩くコードを作成し紹介しました。
この記事が転職を考えている人の情報収集やdockerの学習に役立てば幸いです。
- 投稿日:2020-08-08T12:52:46+09:00
【学習メモ】Docker(Docker運用の流れ、Linux操作、コマンド操作の基本)
なぜDockerを採用するのか?
コンテナ1つ作れば、テスト環境・本番環境もコンテナ起動でOKになるから
Dockerなしの場合
1回1回、テスト・開発・本番環境ごとにインストーラをダウンロード、起動、エラー修正しなきゃいけないしかもチーム開発だと、全く同じバージョンの同じアプリで同じ挙動をしないといけないため大変
Linuxについて
・Linuxのコンテナ技術を利用するので、Linuxの知識が必要
・Linux:Unixをベースに1から作ったオープンソースのOS
・ターミナルでは、Shellを仲介してKernelに命令を出している
・Shell:bazh,zsh,shなど
・Shellを起動するために必要なアプリがターミナルであって、Shell=ターミナルではないDockerを使ってみる
運用の流れ
・Docker imageを管理するDockerHubから自分のhostに、Docker imageを持ってくる
・Docker imageをbashでコンテナ起動
・コンテナでの作業が終わったらexitかdetach
・Hostに戻ったときに、現在のコンテナの状況をps-a、imagesで確認
・exit状態にあるコンテナを再起動
・コンテナをcommitして新しいimageを作成する(=更新内容をDocker imageにする)
・DockerHubにアップする際、リポジトリ名と一致する必要があるので、古いimageを新しいimage名に変更する
・その後保存したDocker imageをDockerHubにpushする
※タグ=バージョン管理コマンド操作の例
$ docker login #Dockerにログイン $ docker pull <image> #DockerHubからDocker imageを出力 $ docker run -it <image> bash #bashはshell。そのDocker imageでコンテナ起動 $ exit #コンテナでの作業を終了 $ docker ps-a #Dockerコンテナ一覧を確認 $ docker images #Docker images一覧を確認 $ docker restart #Dockerを再起動 $ docker exec -it <container> bash #特定のコンテナで作業開始 $ docker commit <container><image> #特定のコンテナの変更をDocker imageに反映 $ docker tag <source> <target> #Docker imageの名前を変更 $ docker push <image> #Docker imageをリポジトリにpush $ docker rmi <image> #Docker imageを削除参考
- 投稿日:2020-08-08T12:49:45+09:00
Django3チュートリアル準備
Django3の環境構築をdockerで行う
環境構築
Django3.0の開発環境をDocker,Docker-compose,Poetryで作ってみた
上記の記事がシンプルで分かりやすかったので、参考にしました。
私の環境では下記のディレクトリー 構造となりました。
Makefileは私が作成したものです。
記事の最後に載せてあります。. ├── Dockerfile ├── docker-compose.yml ├── Makefile └── src ├── manage.py ├── project ├── pyproject.toml └── poetry.lockgit管理する
//git config でユーザー名と設定 git config --global user.email "xxx.yyy@example" git config --global user.name "password" //git hubでリポジトリの作成後リモートリポジトリの追加をします。 git remote add origin [remote repository PATH] //git pullを実行し設定終了 git pull.gitignore 作成
Djangoについて全くと言っていいほど理解しておらず【gitignore】に追加すべきファイルがわからなったので、gitignore.ioで作成
https://www.toptal.com/developers/gitignoreMakefile作成
dockerコマンドは長いので打つのが面倒なので、Makefileに記述しています。
up: docker-compose up -d build: docker-compose build --no-cache --force-rm stop: docker-compose stop down: docker-compose down restart: @make down @make up destroy: docker-compose down --rmi all --volumes django: docker exec -it django3_django_1 bash参考にさせていただいた記事
Django3.0の開発環境をDocker,Docker-compose,Poetryで作ってみた
#django 用の .gitignore を一瞬で自動生成する
- 投稿日:2020-08-08T11:35:50+09:00
Docker で CPU 使用率 100% のコンテナを軽減・回避する
foreach
ループを使い Server-Sent Events を監視している Docker コンテナがあります。
コンテナを起動して、しばらくするとマシンが「フォーーっ」と唸り始めたので、docker stats
コマンドで確認すると CPU 使用率が 100% を超えていました。どうしようQiita 記事に絞って「Docker CPU 使用率 100% コンテナ 軽減」でググってもヒットしなかったので、自分のググラビリティとして。
TL; DR
for
/foreach
/while
ループ内の処理の最後に支障をきたさない範囲でsleep
を入れる。0.5 秒入れるだけでも劇的に変わる。その上で Docker もしくは docker-compose の設定で最大使用率に制限をかけるのがベター。
TS; DR
強制的に制限する(
docker
編)もともと Docker にはコンテナごとに CPU の最大使用率を制限するオプション
--cpus
があります。これは、コンテナに対し使用する CPU の個数を指定でき、リソースを分配することができます。例えば4コア CPU の場合、以下は使用率を最大 50% に制限できます。
2つぶんのCPUを割り当てる(2/4=0.5=50%)docker run -it --cpus="2" ubuntu /bin/bash最大 80% に制限したい場合は以下。
3.2個ぶんのCPUを割り当てる(3.2/4=0.8=80%)docker run -it --cpus="3.2" ubuntu /bin/bash
- 参考文献
- Configure the default CFS scheduler | CPU @ Docker 公式ドキュメント
- Docker コンテナの CPU 使用率を制限する Tips @ Qiita
強制的に制限する(
docker-compose
編)
docker-compose
で制限したい場合は、deploy
ディレクティブでcpus
を指定します。docker-compose.ymlversion: '3.8' services: my-service: container_name: my-cont1 build: . deploy: resources: limits: cpus: "1"注意点として、
deploy
の項目は基本的に Docker Swarm 用の設定であるため、docker-compose
では無視されてしまいます。docker-compose up
コマンド実行時に--compatibility
オプションをつけると、docker-compose
互換で動作します。compatibilityオプションを付けないとdeployの内容は有効にならないdocker-compose --compatibility up
- 参考文献:
docker-compose --help
- How to specify Memory & CPU limit in docker compose version 3 @ StackOverflow
しかし、これは制限をかけるだけです。そもそも、抜本的に CPU の使用率を下げない限り、リソースは制限値まで無駄に消費されることになります。おそらく、Docker の問題ではなく、プログラムの組み方に問題があるのは容易に想像できます。
プログラムを見直す
Server-Sent Events のメッセージを受信するために SSL 接続のソケットからデータを読み込み、処理を行うループ箇所が臭います。
どうやら、データが流れてこない間は処理を行わないため、空ループが発生してしまうのが原因のようです。つまり、何も処理しない最速のループが実行されているわけで、「そりゃ CPU 使用率 100% になるわ」と納得しました。
そこで、PHP の「ループ処理を行った際の CPU の負荷」や .NET の「CPU使用率100%を回避する方法」を参考に、試しに1秒間の
sleep
をループの最後に入れてみました。これが、効果的てきめん! 100〜110% であった使用率が 0.00〜0.01% をウロチョロする程度にまで押さえ込めました。0.5 秒でも 0.01〜0.03% 程度でした。
以上から、まずはループ箇所を見直し、ループの支障を来さない範囲で
sleep
を入れるのは効果的だと思います。その上で、保険としてdocker
やdocker-compose
のcpus
で最大値を制限するのがベターだと思われます。参考文献
- Dockerのメモリ使用量を確認したい @ Qiita
- Dockerリソース使用状況の確認方法 @ Qiita
- ループ処理を行った際のCPUの負荷 @ Qiita
- CPU使用率100%を回避する方法 | 旧@IT会議室 @ @IT
- 投稿日:2020-08-08T04:16:19+09:00
ローカルにdockerを使ってHTTPS環境を立ち上げるスニペット
皆さん良いWEBライフ送れていますか?
今回はいつも困るローカルでのSSL環境構築です。内容を見ていただけたらわかりますが、基本mkcertに頼りっぱなしになっています。一度mkcertで設定してしまえば、opensslコマンドで証明書を作る際に面倒なオレオレ認証局署名やSSL証明書自体のインストールの手間が省けるので、今の所採用しています。
目次
- コード全貌
- ファイル構成
- docker-compose.yml
- ssl.conf
- 手順
- 解説
- docker-compose.yml
- ssl.conf
- まとめ
1. コード全般
1-1. ファイル構成
project-root: - docker-compose.yml docker: - ssl.conf ssl: - example.com-key.pem - example.com.pem public: - index.html1-2. docker-compose.yml
version: '3' services: web: image: nginx:latest container_name: 'ssl_web' ports: - '4430:443' volumes: - ./docker/ssl:/etc/nginx/ssl - ./docker/ssl.conf:/etc/nginx/conf.d/default.conf - ./public:/var/www/html1-3 ssl.conf
server { listen 443 ssl; server_name localhost; root /var/www/html; index index.html; ssl_certificate /etc/nginx/ssl/example.com.pem; # SSL証明書 ssl_certificate_key /etc/nginx/ssl/example.com-key.pem; # 秘密鍵 }※ 証明書のファイル名は適宜変更してください
2. 手順
brew install mkcert mkcert -install cd project-root/docker/ssl # ここで証明書ファイルを作っています。 mkcert example.com cd ../../ docker-compose up -dアクセス方法
- PCの場合:
https://127.0.0.1:4330
- スマホの場合:
https://{ifconfigなどで表示されたローカルIP}:4330
※ localhostだとdockerがうまく解釈できないのでIP指定にしています。
3. 解説
3-1. docker-compose.yml
image: nginx:latestconfがnginxのフォーマットなのでnginxにしていますが、confさえWEBサーバーにあったものを書ければapacheでも動くと思います。
ports: - '4430:443'自分でも理解しきれていませんがハマったポイントです。
443:443
といったlocalhostの443ポートをdockerの443ポートに繋げる記述でも動くと思っていましたが、4430:443
とlocalhost側のポートは通常のSSLポートと変えてあげる必要があるようです。volumes: - ./docker/ssl:/etc/nginx/ssl - ./docker/ssl.conf:/etc/nginx/conf.d/default.conf - ./public:/var/www/htmlローカルのディレクトリ、ファイルをdockerにマウントしています。
- ./docker/ssl:/etc/nginx/sslsslディレクトリに関しては証明書ファイルをマウントしているだけです。
- ./docker/ssl.conf:/etc/nginx/conf.d/default.confssl.confはnginxイメージのデフォルトの設定ファイルを上書きする設定にしています。default.confを指定して上書きしないとややこしかったのでこうしています。
- ./public:/var/www/htmlpublicディレクトリ以下のhtmlファイルなどをnginxのドキュメントルート以下にマウントしています。
nginxのデフォルトルートのままだと、index.htmlがすでに存在していてシンプルにマウント出来なかったので、あえて別ディレクトリをドキュメントルートに設定しています。3-2. ssl.conf
ssl_certificate /etc/nginx/ssl/example.com.pem; # SSL証明書 ssl_certificate_key /etc/nginx/ssl/example.com-key.pem; # 秘密鍵特に解説することもないですが、上記でdockerにマウントした証明書や鍵を読み込んでいます。
4. まとめ
mkcertを使うことでとても簡易にSSL環境が構築できると思います。
dockerで出来るというのも環境を汚さなくて良いですね。良いWEBライフを!
- 投稿日:2020-08-08T03:09:54+09:00
Andorid Native + Flutterのビルドに便利なDocker Imageを作る
Androidアプリのビルドによう使うツールをインストールしたDocker Imageの作り方を説明する(Android SDK, Flutter SDK, GCloud, Bundler, Firebase tools)。
Dockerを使ったことはあるが、実用的なDocker Imageを作ったことはない人向けの説明。Docker Imageを作る手順
1. Dockerfileを記述する
# BaseはCircle CIのものにする。android sdk, gcloudが既に入っているので楽。 FROM circleci/android:api-29-node # Install firebase tools RUN sudo curl -sL https://firebase.tools | bash # Install tools for easylauncher RUN sudo apt-get update && sudo apt-get install -y fontconfig ttf-dejavu # Install Flutter SDK # ほぼ以下のファイルのコピペ。flutter_verisonの初期化とprecacheの部分は独自。 # https://github.com/cirruslabs/docker-images-flutter/blob/master/sdk/Dockerfile ARG flutter_version=1.20.1 ENV FLUTTER_HOME=${HOME}/sdks/flutter \ FLUTTER_VERSION=$flutter_version ENV FLUTTER_ROOT=$FLUTTER_HOME ENV PATH ${PATH}:${FLUTTER_HOME}/bin:${FLUTTER_HOME}/bin/cache/dart-sdk/bin RUN git clone --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME} RUN flutter precache RUN yes | flutter doctor --android-licenses && flutter doctor2. Docker Imageをビルドする
上記のDockerfileと同じディレクトリで以下のコマンドを実行する。
docker build -t kamikazezirou/android:1.0 .「kamikazezirou/android」の部分はImage名。
「:1.0」は、ImageのTag。
適宜変更すること。3. Docker ImageをDocker Hubにpushする
docker push kamikazezirou/android:1.0※docker loginでDocker Hubにログインしておくこと。アカウントも必要。
4. CIから使う(Cirlce CIでの例)
jobs: build: working_directory: ~/code docker: - image: kamikazezirou/android:1.0 ...背景
仕事で開発しているアプリで、Android Native onlyのアプリにFlutterモジュールを組み込むことになった。
仕事のAndroidアプリ開発ではCirlce CIを使っているが、その設定をしていて、ビルドツール全部入りのDocker Imageが必要になった。CIのワークフローはは、デバッグapkのビルド -> Firebase Test Lab実行 -> リリースビルドというような流れにしている。最初は、ビルドのDocker Imageには「cirrusci/flutter:1.17.5」を使い、Firebase Test Labの実行のDocker Imageには「circleci/android:api-28-node」を使う、といった形にしようとした(前者はFlutter SDK有り かつ GCloudなし。後者はFlutter SDKなし かつ GCloudあり)。
この方式だと2つ問題があった。
- 依存ライブラリのキャッシュの復元時にエラーが発生した(2つのDocker Imageのhomeディレクトリが違うことが原因)
- この2つのDocker Imageに含まれないビルドツールがあり、それらを毎回インストールする必要があった(→ビルド時間が遅くなる、ビルドスクリプトが雑然とする)
この2つの問題を解決するために、ビルドツール全部入りのDocker Imageを作ろうと思い立った。
1つのDocker Imageであればhomeディレクトリは常に同じであり、ビルドツールのインストール処理も不要。参考:作ったDocker Image
https://hub.docker.com/repository/docker/kamikazezirou/android