- 投稿日:2020-07-08T23:33:30+09:00
PrometheusのNode exporterをdockerで起動してちゃんとホスト側のメトリクスを収集させる方法
docker run -d \ -v "/proc:/host/proc:ro" \ -v "/sys:/host/sys:ro" \ -v "/:/rootfs:ro" \ --net="host" \ quay.io/prometheus/node-exporter
- 投稿日:2020-07-08T22:30:53+09:00
Railsでdeviseを追加したいのにbundle installができない
dockerで環境構築を行いgemの追加をした際にエラーが発生しましたので
備忘録として情報共有しようと思います!開発環境
docker
rails (5.2.0)
ruby (2.7.1)
mysql (5.7)
nginx
puma※docker-compose buildでgemの更新をしますが時間がかかるので下記の記事を参考に
gemの更新を素早くする設定をしています。
https://qiita.com/neko-neko/items/abe912eba9c113fd527eエラー内容
Gemfileでdeviseのgemを追加し、docker-compose run --rm rails bundle installをしたところ以下のエラーが発生
~ RailsApp % docker-compose run --rm rails bundle install Starting railsapp_db_1 ... done Fetching gem metadata from https://rubygems.org/............. Fetching gem metadata from https://rubygems.org/. Resolving dependencies.... Bundler could not find compatible versions for gem "railties": In snapshot (Gemfile.lock): railties (= 5.2.4.3) In Gemfile: devise (= 4.1.0) was resolved to 4.1.0, which depends on railties (< 5.1, >= 4.1.0) rails (~> 5.2.2) was resolved to 5.2.4.3, which depends on railties (= 5.2.4.3) Running `bundle update` will rebuild your snapshot from scratch, using only the gems in your Gemfile, which may resolve the conflict.何が原因なのかわからなかったが、とりあえず「bundle updateしたら解決するかもよ」と書いてあったので
docker-compose run --rm rails bundle updateを実行↓↓↓↓↓↓↓↓
~ RailsApp % docker-compose run --rm rails bundle update Starting railsapp_db_1 ... done Fetching gem metadata from https://rubygems.org/............. Fetching gem metadata from https://rubygems.org/. Resolving dependencies........................... Bundler could not find compatible versions for gem "railties": In snapshot (Gemfile.lock): railties (= 5.2.4.3) In Gemfile: devise (= 4.1.0) was resolved to 4.1.0, which depends on railties (< 5.1, >= 4.1.0) rails (~> 5.2.2) was resolved to 5.2.4.3, which depends on railties (= 5.2.4.3)ダメでしたね・・・
原因
結論から申し上げるとdeviseというgemがlistにないことがエラーの原因だったみたいです。
下記の記事を参考にさせていただきました。
https://qiita.com/hatorijobs/items/2928e152f22d009b07d0こちらの記事をそのまま実行すれば解決しますが、dockerで作業している方は若干、コマンドが
異なりますのでこちらで説明させていただこうと思います。対処方法
以下の順に操作をしていきます。
1. docker-compose exec [任意サービス名] gem list でGemの一覧を確認し、deviseのgemがないことを確認する。 2. docker-compose exec [任意サービス名] gem install devise でdeviseをインストールする。 3. もう一度docker-compose exec [任意のサービス名] gem list でGemの一覧を確認し、devise(4.7.2)があることを確認する。 4. Gemfileに**gem 'devise','4.7.2'を記述する 5. docker-compose run --rm rails bundle updateを実行順番に見ていきましょう。
↓↓↓↓↓↓↓↓1. docker-compose exec [任意サービス名] gem list でGemの一覧を確認し、deviseのgemがないことを確認する。
~ RailsApp % docker-compose exec app gem list *** LOCAL GEMS *** actioncable (5.2.4.3, 5.2.2) actionmailer (5.2.4.3, 5.2.2) actionpack (5.2.4.3, 5.2.2) actionview (5.2.4.3, 5.2.2) actionjob (5.2.4.3, 5.2.2) ~省略~ web-console (3.7.0)2. docker-compose exec [任意サービス名] gem install devise でdeviseをインストールする。
~ RailsApp % docker-compose exec app gem install devise Fetching warden-1.2.8.gem Fetching bcrypt-3.1.13.gem ~省略~ Successfully installed devise-4.7.2 5 gems installed3. もう一度docker-compose exec [任意のサービス名] gem list でGemの一覧を確認し、devise(4.7.2)があることを確認する。
~ RailsApp % docker-compose exec app gem list *** LOCAL GEMS *** actioncable (5.2.4.3, 5.2.2) actionmailer (5.2.4.3, 5.2.2) actionpack (5.2.4.3, 5.2.2) actionview (5.2.4.3, 5.2.2) actionjob (5.2.4.3, 5.2.2) ~省略~ devise (4.7.2) ~省略~ web-console (3.7.0)4. Gemfileにgem 'devise','4.7.2'を記述する
Gemfile.source 'https://rubygems.org' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.0.0', '>= 5.0.2.1' # Use mysql as the database for Active Record gem 'mysql2', '>= 0.3.18', '< 0.5' # Use Puma as the app server ~省略~ #ログイン機能の追加 gem 'devise','4.7.2' ~省略~5. docker-compose run --rm rails bundle updateを実行
~ RailsApp % docker-compose run --rm rails bundle updateこれでエラーが出なければ我々の勝ちです
気づいたこと
エラー対応している際に気づいたことがいくつかあったので共有させていただきます
docker-compose exec app gem install deviseを実行すると最新版のgemがインストールされます。 最新版でも特に問題ないと判断したため、バージョン指定する方法の説明は省略させていただきました。 ※逆に方法がわかる方は教えてください!ちなみにdeviseの全バージョン履歴が掲載されたサイトを見つけましたのでURLを連携させていただきます。
https://rubygems.org/gems/devise/versions
※2020.06.10時点での最新バージョンは4.7.2
[任意のサービス名]とはdocker-compose.ymlで指定しているサービス名のことです。 任意で決めることができますが、どのサイトでもdbとかappとかwebて設定している方が多い印象です。※わからないて方は、「docker-compose.yml サービス名」で調べると記事がヒットすると思います。
終わりに
Railsやdockerについては今後もアウトプットのためにエラーに関する記事等を定期的に投稿していこうと思っております。
また、初めての投稿で至らない点があったかと思いますが、最後まで読んでいただきありがとうございました!!!以上
- 投稿日:2020-07-08T22:30:28+09:00
dockerでrails+mySQLの環境構築したらlocalhost:3000にアクセス出来なくて困ってたら驚愕の事実が発覚した話
こちらの記事を参考に、docker-composeでrails+mySQLの環境構築をしてみた。
DBの作成まですんなり行き「docker最高!!!!!!!!」みたいになってたが、localhost:3000にアクセスすると「このページは動作していません。」と返ってくる…
うーわ、最悪
環境構築には嫌な思い出しかない。
一度virtualboxとvagrantで環境構築したとき無限にエラーが出続けて「これはもう神がプログラミングをやめろと言っているのでは???」みたいになって以来、環境構築という単語を聞いただけで寒気がしてくる。まあプログラミングの学習をする上で避けては通れない道なのでやるしかない。
とりあえずコンテナ内のサーバーが起動しているか確認。
$ docker exec -it コンテナ名 bash **** # curl http://localhost:3000/コンテナの中に入ってlocalhost:3000にアクセスしてみると普通にHTMLが返ってくる。こっちは問題なさそう。
とりあえずログを見てみる。
docker logs ***_***_web見たけど特にエラーは出ていない。
もう一度コンテナ内からアクセスしたのちログをみると、さっきと同様のログが一つ増えていたので多分このログはコンテナ内からアクセスしたものっぽい。ブラウザからアクセスしてもログが残っていないということは、そもそもブラウザからWebコンテナの3000ポートまでリクエストが到達してないってことらしい。
なるほどね……………ドユコト???クッソ、横文字ばっか並べやがって…
その後も格闘は続いた。ありとあらゆるサイトを読み漁り、英語を必死に読解し、嫌になってスプラトゥーンをやって、YouTubeを見て、twitterを見て…とかなんとかしているうちに夜になっていた。
もう諦めようか…そんな考えが頭をよぎり出したとき、ある記事が目に入る。
私と同じようなエラーが出て困っているようだったのだが、その人が「esetのファイアウォールを無効にしたらいけました〜」と言うているのだ。eset??まって私もセキュリティソフトesetだわ、ウイルスバスターって名前がダサくて嫌だったから特に何も考えずに購入したeset…まさかお前が…?いや、こんな悩みに悩んだ挙句セキュリティソフトに通信遮断されてました!は流石に酷いと思わない…???ねえ、違うよね??違うって言ってよ!!!
とか思いながら恐る恐るesetのファイアウォールを無効にしてlocalhost:3000にアクセスしてみたら
で、出た〜〜〜〜〜〜〜〜〜!!!!!!!!!!!!お前、あっさり出た〜〜〜〜〜〜〜〜!!!!!!!!
くそがよ
- 投稿日:2020-07-08T22:30:28+09:00
dockerでrails+mySQLの環境構築したけどlocalhost:3000にアクセス出来なくて困ってたら驚愕の事実が発覚した話
こちらの記事を参考に、docker-composeでrails+mySQLの環境構築をしてみた。
DBの作成まですんなり行き「docker最高!!!!!!!!」みたいになってたが、localhost:3000にアクセスすると「このページは動作していません。」と返ってくる…
うーわ、最悪
環境構築には嫌な思い出しかない。
一度virtualboxとvagrantで環境構築したとき無限にエラーが出続けて「これはもう神がプログラミングをやめろと言っているのでは???」みたいになって以来、環境構築という単語を聞いただけで寒気がしてくる。まあプログラミングの学習をする上で避けては通れない道なのでやるしかない。
とりあえずコンテナ内のサーバーが起動しているか確認。
$ docker exec -it コンテナ名 bash **** # curl http://localhost:3000/コンテナの中に入ってlocalhost:3000にアクセスしてみると普通にHTMLが返ってくる。こっちは問題なさそう。
次にログを見てみる。
docker logs ***_***_web見たけど特にエラーは出ていない。
もう一度コンテナ内からアクセスしたのちログをみると、さっきと同様のログが一つ増えていたので多分このログはコンテナ内からアクセスしたものっぽい。ブラウザからアクセスしてもログが残っていないということは、そもそもブラウザからWebコンテナの3000ポートまでリクエストが到達してないってことらしい。
なるほどね……………ドユコト???クッソ、横文字ばっか並べやがって…
その後も格闘は続いた。ありとあらゆるサイトを読み漁り、英語を必死に読解し、嫌になってスプラトゥーンをやって、YouTubeを見て、twitterを見て…とかなんとかしているうちに夜になっていた。
もう諦めようか…そんな考えが頭をよぎり出したとき、ある記事が目に入る。
私と同じようなエラーが出て困っているようだったのだが、その人が「esetのファイアウォールを無効にしたらいけました〜」と言うているのだ。eset??まって私もセキュリティソフトesetだわ、ウイルスバスターって名前がダサくて嫌だったから特に何も考えずに購入したeset…まさかお前が…?いや、こんな悩みに悩んだ挙句セキュリティソフトに通信遮断されてました!は流石に酷いと思わない…???ねえ、違うよね??違うって言ってよ!!!
とか思いながら恐る恐るesetのファイアウォールを無効にしてlocalhost:3000にアクセスしてみたら
で、出た〜〜〜〜〜〜〜〜〜!!!!!!!!!!!!お前、あっさり出た〜〜〜〜〜〜〜〜!!!!!!!!
くそがよ
- 投稿日:2020-07-08T21:31:33+09:00
Docker&Rails環境で、gemを永続化させる
本記事について(お断り)
この記事は、しがないプログラミング初心者がお勉強よろしくプログラミング・技術に触れるべく、行ったことの備忘録として書き綴ったものです。ご了承ください。
ご指摘は甘んじて受け入れます?♂️起こったこと
とあるプロダクトでおもむろに
docker-compose up
してたら、... web_1 | Bundler::GemNotFound: Could not find gem 'rspec-rails' in any of the gem sources listed in your Gemfile. ... myapp_web_1 exited with code 1と怒って勝手に出て行ってしまった。
おかしい、確かにインストールしたはずのgemがないとは、、、一度落として、再度
docker-compose build
すると問題なく動いた。
まあこれでもいいんだけど、毎回ビルドしてコンテナ起動するのは面倒だと思う。調べてみると、volumeの永続化を行うことで、こうした問題が解消されるとのこと。
docker-compose.ymlの修正
現在のファイルの中身。
docker-compose.ymlersion: '3' services: db: image: postgres volumes: - ./tmp/db:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=password web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000" depends_on: - dbこれを書き加える
docker-compose.ymlersion: '3' services: db: image: postgres volumes: - ./tmp/db:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=password web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp - gem_data:/usr/local/bundle # <= ココと ports: - "3000:3000" depends_on: - db volumes: gem_data: # <= ココ。パスは、コンテナの中に入って確認できます。
$ docker-compose exec web bash $ gem environment RubyGems Environment: - RUBYGEMS VERSION: 3.0.3 - RUBY VERSION: 2.6.5 (2019-10-01 patchlevel 114) [x86_64-linux] - INSTALLATION DIRECTORY: /usr/local/bundle ...(略)これでgemを永続化する環境を構築できたことになります。
試しに、gemを追加、Gemfile+ gem 'rails-erd'その後、
bundle install
してみます。$ docker-compose exec web bundle installそして、一度コンテナを削除した後に再度起動してみます。
$ docker-compose down $ docker-compose up問題なくコンテナを起動できました!
コンテナ削除前にインストールしたgemもちゃんと入っています。
$ docker-compose exec web bundle list |grep 'rails-erd' * rails-erd (1.6.0)参考
今回の作業にあたり、以下のページを参考にさせていただきました。とても勉強になりました。ありがとうございます?♂️
- 投稿日:2020-07-08T18:36:43+09:00
Riken_simulatorが偶然弊社のOSXでbuild出来てしまった話
はじめに
弊社に設置してあるOSX(iMac)でdockerいじってたら、面白そうなシミュレータの記事が出てたので、
commitできる余地があればと思い本記事を投稿するに至りました。参考にした記事はこちらになります。
自分がした操作は、以下の通りになります。
操作
- 上記記事に記載のDockerfile(下記)を丸パクリ。
FROM ubuntu:18.04 MAINTAINER kaityo256 ENV USER user ENV HOME /home/${USER} ENV SHELL /bin/bash RUN useradd -m ${USER} RUN gpasswd -a ${USER} sudo RUN echo 'user:userpass' | chpasswd RUN apt-get update && apt-get install -y \ g++ \ g++-8-aarch64-linux-gnu \ git \ m4 \ python-dev \ scons \ sudo \ vim \ qemu-user-binfmt \ zlib1g-dev USER ${USER} RUN cd ${HOME} \ && mkdir build \ && cd build \ && git clone --depth 1 https://github.com/RIKEN-RCCS/riken_simulator.git RUN cd ${HOME} \ && cd build/riken_simulator \ && sed -i "369,372s:^:#:" SConstruct \ && scons build/ARM/gem5.opt -j 20 RUN cd ${HOME} \ && git clone https://github.com/kaityo256/aarch64env.git RUN cd ${HOME} \ && echo alias gem5=\'~/build/riken_simulator/build/ARM/gem5.opt ~/build/riken_simulator/configs/example/se.py -c\' >> .bashrc \ && echo alias ag++=\'aarch64-linux-gnu-g++-8 -static -march=armv8-a+sve\' >> .bashrc2 . 上記Dockerfileを配置しているディレクトリにホストOS上で移動し、
docker build -t aarch64env .
3. scons コマンドでこけてbuild未完了のdocker imageに対して、docker run --rm -it ${IMAGEID} /bin/bash
4. riken_simulator/.git/hooks以下(.git以下だったかな...?)の中身に対してrm -rf ./*
という暴挙。
5.cd ~/build/riken_simulator && git init
6. sconsのbuild process時に使用するcore数を -j 4に変更し、containerにloginした状態で再度sed -i "369,372s:^:#:" SConstruct && scons build/ARM/gem5.opt -j 4
結果
時々iMacのdisplayをダウンさせながらも、余計なことを並列でしなければsimulatorは動作する。
build後に
docker network prune
でなぜかパフォーマンスが改善する現象を発見した。Log (上記操作3以降)
user@67870d4b0466:~/build/riken_simulator$ cd .git/hooks user@67870d4b0466:~/build/riken_simulator/.git/hooks$ ls applypatch-msg.sample fsmonitor-watchman.sample pre-applypatch.sample pre-merge-commit.sample pre-rebase.sample prepare-commit-msg.sample commit-msg.sample post-update.sample pre-commit.sample pre-push.sample pre-receive.sample update.sample user@67870d4b0466:~/build/riken_simulator/.git/hooks$ cd .. user@67870d4b0466:~/build/riken_simulator/.git$ rm -r hooks rm: descend into write-protected directory 'hooks'? user@67870d4b0466:~/build/riken_simulator/.git$ ls HEAD config description hooks index info logs objects packed-refs refs user@67870d4b0466:~/build/riken_simulator/.git$ cd hooks user@67870d4b0466:~/build/riken_simulator/.git/hooks$ ls applypatch-msg.sample fsmonitor-watchman.sample pre-applypatch.sample pre-merge-commit.sample pre-rebase.sample prepare-commit-msg.sample commit-msg.sample post-update.sample pre-commit.sample pre-push.sample pre-receive.sample update.sample user@67870d4b0466:~/build/riken_simulator/.git/hooks$ rm ./* rm: remove write-protected regular file './applypatch-msg.sample'? yes rm: cannot remove './applypatch-msg.sample': Permission denied rm: remove write-protected regular file './commit-msg.sample'? ^C user@67870d4b0466:~/build/riken_simulator/.git/hooks$ sudo rm ./* user@67870d4b0466:~/build/riken_simulator/.git/hooks$ ls user@67870d4b0466:~/build/riken_simulator/.git/hooks$ cd ../.. user@67870d4b0466:~/build/riken_simulator$ git init fatal: cannot copy '/home/user/.git_template/hooks/pre-commit' to '/home/user/build/riken_simulator/.git/hooks/pre-commit': Permission denied user@67870d4b0466:~/build/riken_simulator$ sudo git init Reinitialized existing Git repository in /home/user/build/riken_simulator/.git/ user@67870d4b0466:~/build/riken_simulator$ sudo sed -i "369,372s:^:#:" SConstruct && scons build/ARM/gem5.opt -j 4 scons: Reading SConscript files ... OSError: [Errno 13] Permission denied: '/home/user/build/riken_simulator/build': File "/home/user/build/riken_simulator/SConstruct", line 253: mkdir(build_root) user@67870d4b0466:~/build/riken_simulator$ sudo sed -i "369,372s:^:#:" SConstruct && sudo scons build/ARM/gem5.opt -j 4 scons: Reading SConscript files ... Warning: Your compiler doesn't support incremental linking and lto at the same time, so lto is being disabled. To force lto on anyway, use the --force-lto option. That will disable partial linking. Warning: Protocol buffer compiler (protoc) not found. Please install protobuf-compiler for tracing support. Checking for C header file Python.h... yes Checking for C library python2.7... yes Checking for C library pthread... yes Checking for C library dl... yes Checking for C library util... yes Checking for C library m... yes Checking for accept(0,0,0) in C++ library None... yes Checking for zlibVersion() in C++ library z... yes Checking for clock_nanosleep(0,0,NULL,NULL) in C library None... yes Checking for timer_create(CLOCK_MONOTONIC, NULL, NULL) in C library None... no Checking for timer_create(CLOCK_MONOTONIC, NULL, NULL) in C library rt... yes Checking for C library tcmalloc... no Checking for C library tcmalloc_minimal... no You can get a 12% performance improvement by installing tcmalloc (libgoogle-perftools-dev package on Ubuntu or RedHat). Checking for char temp; backtrace_symbols_fd((void*)&temp, 0, 0) in C library None... yes Checking for C header file fenv.h... yes Checking for C header file png.h... no Warning: Header file <png.h> not found. This host has no libpng library. Disabling support for PNG framebuffers. Checking for C header file linux/kvm.h... yes Checking for C header file linux/if_tun.h... yes Checking size of struct kvm_xsave ... yes Checking for member exclude_host in struct perf_event_attr...yes (以下略)考察
作業環境の問題(弊iMacのCPUのCore数の問題)もあってか、ホストOSの作業を減らさないとbuild option -j 4ではかなり動作が遅くなってしまう模様。
ただ試してみるだけなら、build option -j 2でbuildした方が良かったのかもしれないです。所感
ビルドに2時間くらいかかった記憶がありましたが、CPUにガンガン負荷をかけつつbuildが成功しました....
あとは、Dockerfileに記載のコマンドを順次実行して、sampleを試してたら、cacheが溜まるのかホストが動かなくなったので、
docker system prune
でオサラバ。
git clone --depth 1
の意味がザックリと理解できたこと、echo ${PASSWORD} | sudo -S command
でワンライナー実行できることなど、小技が学べたのが良かったです。上記のみでは再現できない可能性がある(途中でやみくもにchmodしてた記憶がある)ので、細かい処理は(もし必要なら)弊社dockerhubレポジトリの:v1のterminal logを参照してください。
現在(2020年7月8日時点)、pipenvも動作するようなall-in-oneコンテナに改変するべくDockerfileを書きなぐっていますが、前回と異なる挙動をする(具体的には、sconsでSyntaxError: except hogehoge , e ^ みたいなエラーで止まる)ので、Docker-engineの送る処理とコマンドライン実行とでは違うのか...?それとも勝手にubuntu20:04に変えたのが間違い...?などと考えを巡らせています。(pipenvとvirtualenvはそもそも分離すべき...?)
参考
- 投稿日:2020-07-08T18:30:28+09:00
Kubernetesにおけるゼロダウンタイムデプロイメント
はじめに
新しいバージョンのアプリケーションをデプロイする時に、アプリケーションをコンテナで運用している場合は、コンテナを作り替える必要がある。デプロイ時に適切な手順を踏まないと、リクエストを正しく捌けずに、クライアントにエラーを返すことになる。これは本番環境で動いているアプリケーションに取ってはクリティカルな問題である。
KubernetesはRollingUpdate
をデフォルトで対応していため、デプロイは適切にManifestを設定をしていればダウンタイムなくデプロイしてくれる。新しいPodの生成からServiceへの追加はヘルスチェック(readnessProbe)を適切に設定するだけで良い。しかし、古いPodを停止する時には、色々考慮する問題が出てくる。適切に設定を行わないと、まだアプリケーションがリクエストを処理中にもかかわらず、Podを停止してしまうということが起こり得る。今回はこの問題を解決するために考察したことをまとめた。KubernetesのPodを停止するまでの挙動
Kubernetesの挙動は以下のようになっている。
Kubernetesでは「
preStop
処理 +SIGTERM
処理」と、「ServiceからのPodの除外処理」が非同期で行われる。コンテナはSIGTERM
のシグナルが送られた場合に、適切に処理中のリクエストを捌き切ってから終了するようにする必要がある。そうでなければ、SIGKILL
シグナルがコンテナに送られて強制終了してしまう。したがって、適切なterminationGracePeriodSeconds
を設定する必要がる。
また、Service
は、該当のコンテナに新しいリクエストを送らないように切り離すが、コンテナが処理を行っている途中である場合は、その接続を切断しないようにしなければいけない。Service (LoadBalancer)
LoadBalancerがコンテナに新しいリクエストを送らないようにするとともに、現在行っている処理の接続を切断しないようにするために、
Connection Draining
の設定をする必要がある。例えば、EKSでは、
Connection Draining
の有効化や、タイムアウトの設定を以下のように設定する。manifestapiVersion: v1 kind: Service metadata: name: test annotations: service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "10" service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout: "10" spec: ...アプリケーションのGraceful Shutdown
コンテナが安全に終了するためには、それぞれのコンテナがGraceful Shutdownをサポートしている必要がある。
例えば、
Gunicorn
はGraceful Shutdownを対応している。適切にgraceful_timeout
の値を設定すれば問題ない。https://docs.gunicorn.org/en/stable/settings.html
また、アプリケーションコンテナの前に
Nginx
のようなリバースプロキシを立てるのはよくある構成だが、その場合、Nginx
も同様に対応していないと、Nginx
が先に終了し、クライアントに504(Gateway Timeout)
が返ってしまう。
Nginx
自体はGraceful Shutdownに対応しているが、Graceful Shutdownを行うためのシグナルが、SIGTERM
ではなく、SIGQUIT
である。TERM, INT fast shutdown QUIT graceful shutdownhttp://nginx.org/en/docs/control.html
そこで、終了時のシグナルを
SIGTERM
からSIGQUIT
に変更してやる必要がある。DockerfileFROM nginx:<version> ... STOPSIGNAL SIGQUIThttps://github.com/nginxinc/docker-nginx/issues/377
また、タイムアウトは
worker_shutdown_timeout
の値を設定する。http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
コンテナ実行時の複数コマンド実行
SIGTERM
シグナルはコンテナ内のPID 1
のプロセスに送られる。コンテナ起動時に複数コマンドを実行したい場合は、Startup Scriptを使うことはあるが、通常のスクリプトを用いると、そのスクリプトがPID 1
を持つことになり、アプリケーションにシグナルが送られない。
そこで、exec
を用いて、スクリプトのプロセスをアプリケーションのプロセスに変更することで対処できる。Dockerfile... ENTRYPOINT ["./startup.sh"] CMD ["runserver"]startup.sh#!/bin/sh set -e # コマンド exec "$@"PID 1問題
LinuxにおけるPID 1は通常
init
である。init
は全てのプロセスの親であるため、このプロセスが殺されると、システムがダウンしてしまうため、特別扱いされている。具体的には、明示的にハンドラを設定していないシグナルは無視される。NAME kill - send signal to a process NOTES The only signals that can be sent to process ID 1, the init process, are those for which init has explicitly installed signal handlers. This is done to assure the system is not brought down accidentally.https://man7.org/linux/man-pages/man2/kill.2.html
したがって、アプリケーションサーバが明示的に
SIGTERM
のハンドラを設定していない場合は、プロセスがSIGTERM
を無視してしまい、終了処理が適切に行われない。Node.js
でこれが起きるらしい。この問題の回避方法は「明示的にシグナルをハンドリングする」または、「アプリケーションのプロセスをPID 1以外で立ち上げる」の2つが考えられる。前者はそれぞれで対応すれば良い。前者が難しい場合は、後者を使う必要がある。
Kubernetes 1.17以上の場合は、ShareProcessNamespace を使ってPID 1を回避できる。
manifestapiVersion: v1 kind: Pod metadata: name: test spec: shareProcessNamespace: true ...Kubernetes以外、またはKubernetesのバージョンが低い場合は、 tiniのような軽量initと呼ばれるライブラリを使えば解決できる。
Dockerfile... ENV TINI_VERSION v0.19.0 ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini RUN chmod +x /tini ENTRYPOINT ["/tini", "--"] CMD ["runserver"]参考
- https://www.amazon.co.jp/dp/4295004804/
- https://text.superbrothers.dev/200328-how-to-avoid-pid-1-problem-in-kubernetes/
- https://ngzm.hateblo.jp/entry/2017/08/22/185224
- https://man7.org/linux/man-pages/man2/kill.2.html
- https://github.com/krallin/tini
- https://docs.gunicorn.org/en/stable/settings.html
- https://stackoverflow.com/questions/58408087/is-there-a-easy-way-to-shut-down-python-grpc-server-gracefully
- https://docs.celeryproject.org/en/stable/userguide/workers.html
- https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/config-conn-drain.html
- https://kubernetes.io/docs/concepts/cluster-administration/cloud-providers/
- http://nginx.org/en/docs/control.html
- https://docs.gunicorn.org/en/stable/settings.html
- https://kubernetes.io/ja/docs/tasks/configure-pod-container/share-process-namespace/
- http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
- https://github.com/nginxinc/docker-nginx/issues/377
- 投稿日:2020-07-08T18:30:28+09:00
Docker(Docker)におけるゼロダウンタイムデプロイメント
はじめに
新しいバージョンのアプリケーションをデプロイする時に、アプリケーションをコンテナで運用している場合は、コンテナを作り替える必要がある。デプロイ時に適切な手順を踏まないと、リクエストを正しく捌けずに、クライアントにエラーを返すことになる。これは本番環境で動いているアプリケーションに取ってはクリティカルな問題である。
KubernetesはRollingUpdate
デフォルトで対応しているため、基本的にはKubebernetesに任せておけばうまく行く。しかし、古いPodを停止する時に、正しく設定を行わないと、まだアプリケーションがリクエストを処理中にもかかわらず、Podを停止してしまう。今回はこの問題を解決するために考察したことをまとめた。KubernetesのPodを停止するまでの挙動
Kubernetesの挙動は以下のようになっている。
Kubernetesでは「
preStop
処理 +SIGTERM
処理」と、「ServiceからのPodの除外処理」が非同期で行われる。コンテナはSIGTERM
のシグナルが送られた場合に、適切に処理中のリクエストを捌き切ってから終了するようにする必要がある。そうでなければ、SIGKILL
シグナルがコンテナに送られて強制終了してしまう。したがって、適切なterminationGracePeriodSeconds
を設定する必要がる。
また、Service
は、該当のコンテナに新しいリクエストを送らないように切り離すが、コンテナが処理を行っている途中である場合は、その接続を切断しないようにしなければいけない。Service (LoadBalancer)
LoadBalancerがコンテナに新しいリクエストを送らないようにするとともに、現在行っている処理の接続を切断しないようにするために、
Connection Draining
の設定をする必要がある。例えば、EKSでは、
Connection Draining
の有効化や、タイムアウトの設定を以下のように設定する。manifestapiVersion: v1 kind: Service metadata: name: test annotations: service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "10" service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout: "10" spec: ...アプリケーションのGraceful Shutdown
コンテナが安全に終了するためには、それぞれ使っているアプリケーションサーバがGraceful Shutdownをサポートしている必要がある。
例えば、
Gunicorn
はGraceful Shutdownを対応している。適切にgraceful_timeout
の値を設定する必要がある。https://docs.gunicorn.org/en/stable/settings.html
また、
Nginx
はGraceful Shutdownに対応しているが、Graceful Shutdownを行うためのシグナルが、SIGTERM
ではなく、SIGQUIT
である。TERM, INT fast shutdown QUIT graceful shutdownhttp://nginx.org/en/docs/control.html
そこで、終了時のシグナルを
SIGTERM
からSIGQUIT
に変更してやる必要がある。DockerfileFROM nginx:<version> ... STOPSIGNAL SIGQUIThttp://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
コンテナ実行時の複数コマンド実行
SIGTERM
シグナルはコンテナ内のPID 1
のプロセスに送られる。コンテナ起動時に複数コマンドを実行したい場合は、Startup Scriptを使うことはあるが、通常のスクリプトを用いると、そのスクリプトがPID 1
を持つことになり、アプリケーションにシグナルが送られない。
そこで、exec
を用いて、スクリプトのプロセスをアプリケーションのプロセスに変更することで対処できる。Dockerfile... ENTRYPOINT ["./startup.sh"] CMD ["python", "runserver"]startup.sh#!/bin/sh set -e # 処理 exec "$@"PID 1問題
LinuxにおけるPID 1は通常
init
である。init
は全てのプロセスの親であるため、このプロセスが殺されると、システムがダウンしてしまうため、特別扱いされている。具体的には、明示的にハンドラを設定していないシグナルは無視される。NAME kill - send signal to a process NOTES The only signals that can be sent to process ID 1, the init process, are those for which init has explicitly installed signal handlers. This is done to assure the system is not brought down accidentally.https://man7.org/linux/man-pages/man2/kill.2.html
したがって、アプリケーションサーバが明示的に
SIGTERM
のハンドラを設定していない場合は、プロセスがSIGTERM
を無視してしまい、終了処理が適切に行われない。Node.js
でこれが起きるらしい。この問題の回避方法は「明示的にシグナルをハンドリングする」または、「アプリケーションのプロセスをPID 1以外で立ち上げる」の2つが考えられる。前者はそれぞれで対応すれば良い。前者が難しい場合は、後者を使う必要がある。
Kubernetes 1.17以上の場合は、ShareProcessNamespace を使ってPID 1を回避できる。
manifestapiVersion: v1 kind: Pod metadata: name: test spec: shareProcessNamespace: true ...Kubernetes以外、またはKubernetesのバージョンが低い場合は、 tiniのような軽量initと呼ばれるライブラリを使えば解決できる。
Dockerfile... ENTRYPOINT ["/tini", "--"] CMD ["python", "runserver"]参考
- https://text.superbrothers.dev/200328-how-to-avoid-pid-1-problem-in-kubernetes/
- https://ngzm.hateblo.jp/entry/2017/08/22/185224
- https://man7.org/linux/man-pages/man2/kill.2.html
- https://github.com/krallin/tini
- https://docs.gunicorn.org/en/stable/settings.html
- https://stackoverflow.com/questions/58408087/is-there-a-easy-way-to-shut-down-python-grpc-server-gracefully
- https://docs.celeryproject.org/en/stable/userguide/workers.html
- https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/config-conn-drain.html
- https://kubernetes.io/docs/concepts/cluster-administration/cloud-providers/
- http://nginx.org/en/docs/control.html
- https://docs.gunicorn.org/en/stable/settings.html
- https://kubernetes.io/ja/docs/tasks/configure-pod-container/share-process-namespace/
- http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
- 投稿日:2020-07-08T18:30:28+09:00
Kubernetes(Docker)におけるゼロダウンタイムデプロイメント
はじめに
新しいバージョンのアプリケーションをデプロイする時に、アプリケーションをコンテナで運用している場合は、コンテナを作り替える必要がある。デプロイ時に適切な手順を踏まないと、リクエストを正しく捌けずに、クライアントにエラーを返すことになる。これは本番環境で動いているアプリケーションに取ってはクリティカルな問題である。
KubernetesはRollingUpdate
デフォルトで対応しているため、基本的にはKubebernetesに任せておけばうまく行く。しかし、古いPodを停止する時に、正しく設定を行わないと、まだアプリケーションがリクエストを処理中にもかかわらず、Podを停止してしまう。今回はこの問題を解決するために考察したことをまとめた。KubernetesのPodを停止するまでの挙動
Kubernetesの挙動は以下のようになっている。
Kubernetesでは「
preStop
処理 +SIGTERM
処理」と、「ServiceからのPodの除外処理」が非同期で行われる。コンテナはSIGTERM
のシグナルが送られた場合に、適切に処理中のリクエストを捌き切ってから終了するようにする必要がある。そうでなければ、SIGKILL
シグナルがコンテナに送られて強制終了してしまう。したがって、適切なterminationGracePeriodSeconds
を設定する必要がる。
また、Service
は、該当のコンテナに新しいリクエストを送らないように切り離すが、コンテナが処理を行っている途中である場合は、その接続を切断しないようにしなければいけない。Service (LoadBalancer)
LoadBalancerがコンテナに新しいリクエストを送らないようにするとともに、現在行っている処理の接続を切断しないようにするために、
Connection Draining
の設定をする必要がある。例えば、EKSでは、
Connection Draining
の有効化や、タイムアウトの設定を以下のように設定する。manifestapiVersion: v1 kind: Service metadata: name: test annotations: service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "10" service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout: "10" spec: ...アプリケーションのGraceful Shutdown
コンテナが安全に終了するためには、それぞれのコンテナがGraceful Shutdownをサポートしている必要がある。
例えば、
Gunicorn
はGraceful Shutdownを対応している。適切にgraceful_timeout
の値を設定すれば問題ない。https://docs.gunicorn.org/en/stable/settings.html
また、アプリケーションコンテナの前に
Nginx
のようなリバースプロキシを立てるのはよくある構成だが、その場合、Nginx
も同様に対応していないと、Nginx
が先に終了し、クライアントに504(Gateway Timeout)
が返ってしまう。
Nginx
自体はGraceful Shutdownに対応しているが、Graceful Shutdownを行うためのシグナルが、SIGTERM
ではなく、SIGQUIT
である。TERM, INT fast shutdown QUIT graceful shutdownhttp://nginx.org/en/docs/control.html
そこで、終了時のシグナルを
SIGTERM
からSIGQUIT
に変更してやる必要がある。DockerfileFROM nginx:<version> ... STOPSIGNAL SIGQUIThttps://github.com/nginxinc/docker-nginx/issues/377
また、タイムアウトは
worker_shutdown_timeout
の値を設定する。http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
コンテナ実行時の複数コマンド実行
SIGTERM
シグナルはコンテナ内のPID 1
のプロセスに送られる。コンテナ起動時に複数コマンドを実行したい場合は、Startup Scriptを使うことはあるが、通常のスクリプトを用いると、そのスクリプトがPID 1
を持つことになり、アプリケーションにシグナルが送られない。
そこで、exec
を用いて、スクリプトのプロセスをアプリケーションのプロセスに変更することで対処できる。Dockerfile... ENTRYPOINT ["./startup.sh"] CMD ["runserver"]startup.sh#!/bin/sh set -e # コマンド exec "$@"PID 1問題
LinuxにおけるPID 1は通常
init
である。init
は全てのプロセスの親であるため、このプロセスが殺されると、システムがダウンしてしまうため、特別扱いされている。具体的には、明示的にハンドラを設定していないシグナルは無視される。NAME kill - send signal to a process NOTES The only signals that can be sent to process ID 1, the init process, are those for which init has explicitly installed signal handlers. This is done to assure the system is not brought down accidentally.https://man7.org/linux/man-pages/man2/kill.2.html
したがって、アプリケーションサーバが明示的に
SIGTERM
のハンドラを設定していない場合は、プロセスがSIGTERM
を無視してしまい、終了処理が適切に行われない。Node.js
でこれが起きるらしい。この問題の回避方法は「明示的にシグナルをハンドリングする」または、「アプリケーションのプロセスをPID 1以外で立ち上げる」の2つが考えられる。前者はそれぞれで対応すれば良い。前者が難しい場合は、後者を使う必要がある。
Kubernetes 1.17以上の場合は、ShareProcessNamespace を使ってPID 1を回避できる。
manifestapiVersion: v1 kind: Pod metadata: name: test spec: shareProcessNamespace: true ...Kubernetes以外、またはKubernetesのバージョンが低い場合は、 tiniのような軽量initと呼ばれるライブラリを使えば解決できる。
Dockerfile... ENTRYPOINT ["/tini", "--"] CMD ["runserver"]参考
- https://www.amazon.co.jp/dp/4295004804/
- https://text.superbrothers.dev/200328-how-to-avoid-pid-1-problem-in-kubernetes/
- https://ngzm.hateblo.jp/entry/2017/08/22/185224
- https://man7.org/linux/man-pages/man2/kill.2.html
- https://github.com/krallin/tini
- https://docs.gunicorn.org/en/stable/settings.html
- https://stackoverflow.com/questions/58408087/is-there-a-easy-way-to-shut-down-python-grpc-server-gracefully
- https://docs.celeryproject.org/en/stable/userguide/workers.html
- https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/config-conn-drain.html
- https://kubernetes.io/docs/concepts/cluster-administration/cloud-providers/
- http://nginx.org/en/docs/control.html
- https://docs.gunicorn.org/en/stable/settings.html
- https://kubernetes.io/ja/docs/tasks/configure-pod-container/share-process-namespace/
- http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
- https://github.com/nginxinc/docker-nginx/issues/377
- 投稿日:2020-07-08T18:21:08+09:00
VPN越しのlinuxマシンにpingが通らない原因がdocker0だった
3ヶ月くらいずっと原因不明だったのがやっと解決したので備忘録として書き留めておく。
事象
⭕ローカルmac <-> ローカルmac
⭕ローカルmac <-> ローカルlinux
⭕ローカルmac <-> VPN越しmac
❌VPN越しmac <-> ローカルlinux要は リモートで何故かlinuxマシンに接続できない! という状況が発生していた。
結論
VPN配下のIPアドレスと
docker0
のIPアドレスが衝突していることが原因だった。
- 今回の環境でVPN配下に割り振られるアドレス:
172.17.XXX.0/21
docker0
のIPアドレス初期値:172.17.0.1/16
これを
docker0
のIPアドレス設定を変更し、dockerサービスを再起動することで解決した。(情シスはこの事象既知なんだろうか)
やったこと
わかっていること
- VPN越しmac -> ローカルlinuxへping:
Request timeout for icmp_seq XX
- ローカルlinux -> VPN越しmacへping:
From 172.17.0.1 icmp_seq=XX Destination Host Unreachable
事前に試してダメだったことのおさらい
今回の件には結局関係なかったけど一応チェックしといてねって箇所
- そもそもicmpが塞がれていないか(検証手段が正しいのか)
- mac同士のpingは通るので塞がれていないことがわかる
host.allow
およびhost.deny
の設定見直し
hosts.allow
に172.19.
と記述しても変化なかった- firewall設定
- 無効化しても変化なかった
自身のアドレスを確認
pingのエラーメッセージから、
172.17.0.1
とかいうよくわからん経路でコケてることは分かっていたふとdocker周りのネットワークが気になったので、自身のアドレスをすべて確認してみることにする
$ hostname -I 172.19.XXX.XXX 172.17.0.1 172.18.0.1 192.168.XXX.XXX ...
172.17.0.1
がいる???なんで???$ ip a ### 略 ### 2: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.30.0.255 scope global docker0 valid_lft forever preferred_lft forever inet6 XXXX::XXXX:XXXX:XXXX:XXXX/64 scope link ### 略 ###
docker0
とかいう仮想インターフェイスがガッツリIPアドレス被りしている模様なので、これを変更してみるちなみに
docker0
はdocker for linuxのみでしか生成されず、これがlinuxへの疎通のみNGという理由にもなっていたdocker0の設定変更
先人の大変ありがたい資料があるので、参考に設定を進める
https://qiita.com/msi/items/d9cc1a2fd3f0fed3a901$ sudo vi /etc/docker/daemon.json { "bip": "172.30.0.254/24" } $ sudo systemctl restart docker $ ip a show docker0 2: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff inet 172.30.0.254/24 brd 172.30.0.255 scope global docker0 valid_lft forever preferred_lft forever inet6 XXXX::XXXX:XXXX:XXXX:XXXX/64 scope linkping
# VPN越しmac -> ローカルlinux $ ping 172.19.XXX.XXX 64 bytes from 172.19.XXX.XXX: icmp_seq=0 ttl=60 time=192.154 ms 64 bytes from 172.19.XXX.XXX: icmp_seq=1 ttl=60 time=238.941 ms 64 bytes from 172.19.XXX.XXX: icmp_seq=2 ttl=60 time=292.419 ms 64 bytes from 172.19.XXX.XXX: icmp_seq=3 ttl=60 time=257.762 ms✌️success✌️
- 投稿日:2020-07-08T17:01:11+09:00
[Docker][Rails] 新しくGemを導入した後の3コマンド
これはなに
Railsでアプリ開発中新しくGemを導入した後、若干躓いたので備忘録として残します。
ご指摘等あれば頂けると幸いです。3コマンド
gem bundle installdocker-compose run web bundle install参考記事
Docker Compose + Railsでイメージ内でbundle installしているはずなのにgemが無いとエラーがでる。docker-compose restart参考記事
dockerの起動、停止、再起動以上です!ありがとうございました!
- 投稿日:2020-07-08T16:44:49+09:00
RabbitMQをインストールする(Windows/Mac/Docker)
最終更新日
2020年7月8日
検証を行ったOS/Dockerのバージョンは下記です。
- Windows 10 Home 64bit 2004 19041.329
- macOS Catalina 10.15.5
- Docker Desktop for Mac 2.3.0.3
インストールするもののバージョンは下記です。
- RabbitMQ 3.8.5
この記事が古くなった場合、下記の手順は最新のインストール手順とは異なっている可能性があります。その場合は公式ドキュメントをご確認ください。
Windowsの場合
Erlangのインストール
(1) https://erlang.org/download/otp_versions_tree.html からEralngのインストーラーをダウンロードしてください。
(2) インストーラーをダブルクリックしてください。
(3) [はい]をクリックしてください。
(4) [Next]をクリックしてください。
(5) [Next]をクリックしてください。
(6) [Install]をクリックしてください。
(7) [Close]をクリックしてください。
RabbitMQのインストール
(1) https://www.rabbitmq.com/install-windows.html#installer からRabbitMQのインストーラーをダウンロードしてください。
(2) インストーラーをダブルクリックしてください。
(3) [はい]をクリックしてください。
(4) [Next]をクリックしてください。
(5) [Install]をクリックしてください。
(6) [Windows セキュリティの重要な警告]が表示されたら[アクセスを許可する]をクリックしてください。
(7) [Next]をクリックしてください。
(8) [Finish]をクリックしてください。
(9) 環境変数
PATH
に、RabbitMQがインストールされたフォルダ\sbin
(例:C:\Program Files\RabbitMQ Server\rabbitmq_server-3.8.5\sbin
)を追加してください。RabbitMQの設定(必要に応じて)
(1) コマンドプロンプトで
rabbitmq-plugins enable rabbitmq_management
を実行してください。(2) コマンドプロンプトで
rabbitmq-plugins enable rabbitmq_tracing
を実行してください。macOSの場合
RabbitMQのインストール
(1) ターミナルで
brew install rabbitmq
を実行してください。Homebrewがインストールされていない場合は、公式サイトを参考にインストールしてください。
(2) 環境変数
PATH
に/usr/local/sbin
を追加してください。(3) ターミナルで
rabbitmq-server
を実行してください。これでRabbitMQが起動します。Ctrl + Cで停止します。
RabbitMQの設定(必要に応じて)
(1) ターミナルで
rabbitmq-plugins enable rabbitmq_management
を実行してください。(2) ターミナルで
rabbitmq-plugins enable rabbitmq_tracing
を実行してください。Dockerの場合
Dockerのインストール方法は別記事にて紹介しています(Windows 10 Proの場合 、 macOSの場合)
(1) 次のようなDockerfileを作成してください。
DockerfileFROM rabbitmq:3.8.5-management-alpine RUN rabbitmq-plugins enable rabbitmq_tracing EXPOSE 5672 15672(2) ターミナル(orコマンドプロンプト)でDockerfileを作成したフォルダに移動して、
docker image build -t rabbitmq-scd .
を実行してください。$ docker image build -t rabbitmq-scd . Sending build context to Docker daemon 2.048kB Step 1/3 : FROM rabbitmq:3.8.5-management-alpine 3.8.5-management-alpine: Pulling from library/rabbitmq df20fa9351a1: Pull complete 6a4ed0140701: Pull complete d144d94e32f5: Pull complete 4d0a1f15085c: Pull complete 3efe37eb67c8: Pull complete 21fb2255fd06: Pull complete 8d1fc732c7d2: Pull complete ebf280fe3644: Pull complete 947f27a4fe95: Pull complete Digest: sha256:7bb012930d5fa185ad5a52e0693096eb4628fba48b9ad7303edb09b80c47ad0c Status: Downloaded newer image for rabbitmq:3.8.5-management-alpine ---> 4e6d459e4748 Step 2/3 : RUN rabbitmq-plugins enable rabbitmq_tracing ---> Running in beba71787921 Enabling plugins on node rabbit@beba71787921: rabbitmq_tracing The following plugins have been configured: rabbitmq_management rabbitmq_management_agent rabbitmq_tracing rabbitmq_web_dispatch Applying plugin configuration to rabbit@beba71787921... The following plugins have been enabled: rabbitmq_tracing set 4 plugins. Offline change; changes will take effect at broker restart. Removing intermediate container beba71787921 ---> 8aacc20abf9a Step 3/3 : EXPOSE 5672 15672 ---> Running in f84d57362063 Removing intermediate container f84d57362063 ---> 0ab7f38dc713 Successfully built 0ab7f38dc713 Successfully tagged rabbitmq-scd:latest(3) ターミナル(orコマンドプロンプト)で
docker container create -p 5672:5672 -p 15672:15672 --name rabbitmq-scd rabbitmq-scd
を実行してください。$ docker container create -p 5672:5672 -p 15672:15672 --name rabbitmq-scd rabbitmq-scd 67473dcbed40bee46c5f9b3531763ed71fd6cd5b6a6cb1364b90da21d621ce59(4) ターミナル(orコマンドプロンプト)で
docker container start rabbitmq-scd
を実行してください。これでRabbitMQが起動します。$ docker container start rabbitmq-scd rabbitmq-scd
docker container stop rabbitmq-scd
で停止します。
- 投稿日:2020-07-08T16:43:50+09:00
dockerのマウントについて 初学者なりに考えた。 自分用のメモ
マウントについて
バインドマウント(bind)
Dockerホストのファイルやディレクトリをコンテナ上にマウントする機能
バインドマウントを行うと、コンテナの外にあるファイルを、コンテナの中から読み書き可能になります。ボリュームマウント(volume)
Docker が管理するデータ領域を コンテナ上にマウントする機能です。
バインドマウントとの違いは、バインドマウントが「Dockerが管理するデータ領域以外もマウント可能である」ことに対し、ボリュームマウントは「Dockerが管理するデータ領域内でのマウントのみ可能である」という点です。
ホストマシン上に新たなディレクトリが生成され、そこが Dockerの保存ディレクトリとなります。 そしてDockerはそのディレクトリ内の内容を管理していきます。コンテナが破棄させるとvolumesに保存される。ホストのデータが更新され、コンテナを立ち上げれば、volumeの既存データもupdateされる。
一時ファイルシステムのマウント(tmpfs)
Dockerホストにファイルとして保存したくないデータを一時的に利用できるようにする(データ領域をメモリ上に置く)機能。
ホストマシンとは
ホストマシンとコンテナでディレクトリを同期させることができるが、 注意しておきたいのが, ここでいうホストマシンとはMacのことではない。
Mac上で起動しているのはdockerの仮想Linuxマシンであること。そもそもコンテナというものはLinuxカーネルに使われている技術。したがってMacでコンテナ技術を使うためには, 間に仮想Linuxマシンをはさまなくてはならない。
Macとコンテナはデータのやりとりができないのかというとそうではない。 仮想Linuxマシンからは, Mac全体が/Macとして参照できるらしい。
つまりMac全体が仮想Linuxマシンにマウントされているとのこと。 他にもMac上の/Usersが仮想Linuxマシンからも/Usersでアクセスできる。実際にdocker run コマンドを使用しバインドマウントを行って見た。
Hostディレクトリ構成docker run -it -d -p 8080:80 -v /Users/hamadayuuta/Desktop/test_dk/test3/:/var/lib/test/ nginx:latestバインドマウント先は任意のコンテナ内のディレクトリが作成可能。
/User~ : まではホストのターゲットpath
/var/lib/ → dockerコンテナ内のpath。環境はlinux環境
/test/は任意のディレクトリを作成。 ここがマウント領域になる。docker exec -it nginx:latest /bin/bashで見にいくと
root@b00e211eff2b:/# cd ./var/lib/test/ root@b00e211eff2b:/var/lib/test# ls index.htmlマウントを確認。
docker inspectで確認すると
"Mounts": [ { "Type": "bind", "Source": "/Users/hamadayuuta/Desktop/test_dk/test3", "Destination": "/var/lib/test",マウントを確認できました。
コンテナはlinuxのプロセス空間を用いて作成したものであるから、 マウントをする際はlinuxのディレクトリ構造をイメージして作成しないといけないかな。→間違えてたらすみません。
- 投稿日:2020-07-08T16:00:13+09:00
Docker ComposeのMySQLに初期データを設定する
初期データ
initdb.d
フォルダを作成してinit.sql
とpet.txt
を配置する。
init.sql
の内容はテーブル削除、作成とデータ挿入を記述init.sqldrop table if exists pet; create table if not exists pet ( name varchar(20) , owner varchar(20) , species varchar(20) , sex char(1) , birth date , death date ); load data local infile '/docker-entrypoint-initdb.d/pet.txt' into table pet;
pet.txt
の内容はテーブルに挿入するデータをcsv形式で記述pet.txtFluffy Harold cat f 1993-02-04 \N Claws Gwen cat m 1994-03-17 \N Buffy Harold dog f 1989-05-13 \N Fang Benny dog m 1990-08-27 \N Bowser Diane dog m 1979-08-31 1995-07-29 Chirpy Gwen bird f 1998-09-11 \N Whistler Gwen bird \N 1997-12-09 \N Slim Benny snake m 1996-04-29 \N設定
docker-compose.yml
のvolumes
に初期データフォルダを記述する。
ローカルのinitdb.d
フォルダをコンテナ内にdocker-entrypoint-initdb.d
フォルダで配置する。
dockerhub - mysqldocker-compose.ymlversion: '3.8' services: mysql: image: mysql:5.7 ports: - "3306:3306" volumes: - db_data:/var/lib/mysql - ./initdb.d:/docker-entrypoint-initdb.d restart: always environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: my_test MYSQL_USER: mysql MYSQL_PASSWORD: mysql volumes: db_data: {}起動
いつも通りにコンテナを起動する。
$ docker-compose up -d終わり
起動後にデータを入れ直す
コンテナを
down --volumes
して再度up
すれば良いんだろうけど。。。
別の方法と言うことで、コンテナ内に入る。
$ docker-compose exec mysql /bin/bashコンテナ内でmysqlコマンドをバッチモードで実行する。
# mysql -u mysql --password=mysql my_test < /docker-entrypoint-initdb.d/init.sql
コンテナ内から出る。
# exit
ほんとに終わり
- 投稿日:2020-07-08T11:00:36+09:00
Ubuntu 16.04での「Docker」のインストールと使い方
このチュートリアルでは、Alibaba CloudにDockerをインストールする方法を探り、コンテナサービスのデプロイと管理に役立ついくつかの重要なDockerコマンドを学びます。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
序章
Dockerは、開発者やシステム管理者向けのオープンソースプロジェクト(コンテナ管理サービス)で、ラップトップ、データセンターのVM、クラウド上で分散アプリケーションを構築、出荷、実行し、コンテナに出荷することで、どこにでもデプロイできるようにします。Dockerは、WindowsとLinuxベースのオペレーティングシステム上でオペレーティングシステムレベルの仮想化の自動化を提供します。
Dockerを使用することで、特定のスタックに依存することなく、簡単にWebアプリ、データベース、バックエンドサービスをデプロイしてスケーリングするためのブロックを構築することができます。Dockerはいくつかのコンポーネントで構成されています。
1)Docker for Linux:Linux OS上でDockerコンテナを実行できるようにします。
2) Docker Engine:Dockerイメージの構築やDockerコンテナの作成に使用します。
3) Docker Hub:様々なDockerイメージを保存するために使用します。
4) Docker Compose: 複数のDockerコンテナを使用してアプリケーションを定義するために使用します。特徴
- Docker Swarmは、Dockerエンジンのグループを単一の仮想Dockerエンジンに変えるDockerコンテナのクラスタリングソリューションを提供します。
- Dockerは、小さなフットプリントのオペレーティングシステムを提供することで、開発の規模を縮小する能力を持っています。
- Dockerコンテナは非常に軽量で、容易に拡張可能です。
- 簡単かつ高速な設定を提供し、生産性を向上させる。
- アイソレーション環境であらゆる種類のアプリケーションを実行できるコンテナを提供する。
このチュートリアルでは、Dockerをインストールする方法を説明し、いくつかの重要なDockerコマンドを説明します。また、コマンドがどのように使われているのか、どのようなことをするのかについて、いくつかのハンズオン体験を共有します。
前提条件
- Ubuntu 16.04をインストールした新鮮なAlibaba Cloud ECSインスタンス。
- インスタンスにルートパスワードが設定されています。
Dockerのインストール
始める前に、Dockerの最新版をサーバーにインストールする必要があります。デフォルトでは、最新版のDockerはUbuntu 16.04のリポジトリでは利用できません。そのため、公式のDockerリポジトリをサーバーに追加する必要があります。
まず、以下のコマンドで公式DockerリポジトリのGPGキーをダウンロードしてシステムに追加します。
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
を実行します。次に、以下のコマンドでDockerリポジトリをaptのソースに追加します。
echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable" | sudo tee -a /etc/apt/sources.list.d/docker.list
次に、リポジトリを更新し、以下のコマンドでDockerをインストールします。
shell apt-get update -y apt-get install docker-ce -yDockerをインストールしたら、以下のコマンドでDockerの状態を確認することができます。
shell systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2017-12-08 20:46:13 IST; 3min 2s ago Docs: https://docs.docker.com Main PID: 926 (dockerd) Tasks: 45 Memory: 79.2M CPU: 7.463s CGroup: /system.slice/docker.service ├─ 926 /usr/bin/dockerd -H fd:// ├─1453 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --st ├─2285 docker-containerd-shim e4202324477ae1870a77e12863ab3c79661cf8b7bfa617bb5709a816ea85194e /var/run/docker/libcontainerd/e420232 └─2290 docker-containerd-shim 97bf4d277e0563906318bb276c3c65ebc274f28b6bb86cce80def795ecba76e2 /var/run/docker/libcontainerd/97bf4d2Dockerイメージのダウンロード
コンテナはDockerイメージを使って構築するので、まずはDockerイメージを引っ張ってくる必要があります。Dockerのサイトにはすでにたくさんのイメージが公開されています。簡単な検索コマンドで任意のイメージを見つけることができます。
例えば、Ubuntu 16.04のイメージを検索するには、以下のコマンドを実行します。
docker search ubuntu:16.04
すると、Dockerのウェブサイトに以下のような画像が公開されているはずです。
shell NAME DESCRIPTION STARS OFFICIAL AUTOMATED ubuntu Ubuntu is a Debian-based Linux operating s... 6917 [OK] ubuntu-upstart Upstart is an event-based replacement for ... 80 [OK] ubuntu-debootstrap debootstrap --variant=minbase --components... 32 [OK] mlaccetti/docker-oracle-java8-ubuntu-16.04 Oracle Java 8 on Ubuntu 16.04 LTS 4 [OK] gocd/gocd-agent-ubuntu-16.04 Docker GoCD agent for Ubuntu 16.04 2 seresearch/opendavinci-ubuntu-16.04 Docker image with all Ubuntu 16.04 depende... 2 [OK] proudmail/ubuntu-16.04 Create ubuntu 16.04 1 [OK] superkumkum/ubuntu-16.04 base image of ubuntu 16.04 0 [OK] gocdexperimental/gocd-agent-ubuntu-16.04 Experimental GoCD Agent - Ubuntu 16.04 0 dokken/ubuntu-16.04 For use with kitchen-dokken, Base image pl... 0 keithf/ubuntu-16.04-armhf Ubuntu 16.04 for ARM-based devices. 0 neoncluster/ubuntu-16.04 Ubuntu 16.04 image with recent package upg... 0 cdbishop89/docker-ubuntu-16.04 Base Ubuntu 16.04 Image 0 [OK] vlex/ubuntu-16.04-node Ubuntu 16.04 with node 6.1.0 0 seresearch/opendavinci-ubuntu-16.04-complete 0 itsspeed/ubuntu-16.04-python Base Ubuntu 16.04 image with python and pi... 0 syseleven/ubuntu-16.04-puppet4 ubuntu-16.04-puppet4 0 [OK] opencpu/ubuntu-16.04 OpenCPU Server builds for Ubuntu 16.04 (Xe... 0 [OK] lgong/mml-ubuntu-16.04 0 stafory/ubuntu-16.04-ci 0 kensenshi/ubuntu-16.04-oracle-java8-ant Oracle Java 8 and ANT on Ubuntu 16.04. 0 naritadev/narita-ubuntu-16.04 Narita Ubuntu 16.04 Distro 0 addle/ubuntu-16.04 Ubuntu 16.04 LTS (Xenial Xerus) 0 uberr2000/ink-ubuntu-16.04 ubuntu 16.04 with nginx ,phalcon ,mysql,ph... 0 syseleven/ubuntu-16.04-puppet5 ubuntu-16.04-puppet5 0 [OK]次に、上記の画像からUbuntu-16.04のベースイメージをダウンロードします。
docker pull ubuntu
出力は以下のようになります。
Using default tag: latest latest: Pulling from library/ubuntu 660c48dd555d: Pull complete 4c7380416e78: Pull complete 421e436b5f80: Pull complete e4ce6c3651b3: Pull complete be588e74bd34: Pull complete Digest: sha256:7c67a2206d3c04703e5c23518707bdd4916c057562dd51c74b99b2ba26af0f79 Status: Downloaded newer image for ubuntu:latestダウンロードが完了したら、以下のコマンドを実行することで、システム上で利用可能なすべてのイメージを一覧表示することができます。
docker images
出力します。
REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 20c44cd7596f 3 weeks ago 123MBDockerコンテナの起動
さて、基本的なubuntu-16.04のコンテナをbashシェルで設定するには、コマンドを1つ実行するだけです。
docker run -i -t ubuntu /bin/bash
以下のような出力が表示されるはずです。
root@0b775c3f606d:/#
さて、Ubuntuのベースイメージとインスタンスの準備ができたら、Apacheサーバをインタラクティブにインストールすることができます。そのためには、ターミナルで以下のコマンドを実行する必要があります。
shell apt-get update -y apt-get install apache2 apache2-utils -yこれで、Ubuntu Dockerコンテナ内でbashシェルを使用していることになります。終了せずにシェルから切り離す、または切り離すには、Ctrl-p + Ctrl-qのエスケープシーケンスを使用します。
これで、Ubuntuインスタンスで行った変更を保存することができます。そのためには、まず、実行中のUbuntuインスタンスのコンテナIDが必要になります。それを取得するには、実行します。
docker ps
以下のような出力が表示されるはずです。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0b775c3f606d ubuntu "/bin/bash" 36 minutes ago Up 36 minutes dreamy_murdockさて、以下のコマンドを実行して、変更内容をubuntu-apacheという名前の新しいイメージとして保存します。
docker commit 0b775c3f606d ubuntu-apache sha256:6997db13c6587d1403c2360515d29028a30de786101c4ec26faddc505f5242c4コンテナIDとイメージ名ubuntu-apacheを使用して変更が保存されていることがわかります。
新しいイメージが実行されているかどうかを確認するには、実行します。docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu-apache latest 6997db13c658 30 seconds ago 261MB ubuntu latest 20c44cd7596f 3 weeks ago 123MBDockerでアプリケーションを起動
これで、Apache Web サーバを含む新しいイメージができました。そのイメージを元にDockerfileをビルドし、必要なファイルを追加することができます。サイトコンテンツのtarballへの相対パスが与えられると、Dockerは自動的にソースのtarまたはzipファイル内のファイルをターゲットディレクトリにアンタールまたはアンジップします。
これを行うには、ホストシステム上にindex.htmlファイルを作成し、カレントディレクトリにあるapplication.tarというtarballに追加する必要があります。
mkdir application nano application/index.html以下の行を追加します。
html <html> Sample Apache Web Page </html>保存してファイルを閉じます。
それでは、tarを使ってWebサイトのディレクトリを圧縮します。
tar -cvf application.tar application
さて、Webサイトの内容をubuntu-apacheイメージに追加するためのDockerfileを作成し、ポート80でApacheを起動します。
nano Dockerfile
以下の行を追加します。
Dockerfile FROM ubuntu-apache ADD application.tar /tmp/ RUN mv /tmp/application/* /var/www/html/ EXPOSE 80 ENTRYPOINT [ "/usr/sbin/apache2ctl" ] CMD [ "-D", "FOREGROUND" ]保存してファイルを閉じます。
上記のDockerfileでは、website.tar内のwebsiteの内容が自動的に/tmp/フォルダに展開されます。そして、サイト全体がApacheのルートディレクトリ/var/www/html/に移動し、expose80が80番ポートを開くので、正常にサイトが利用できるようになります。そして、エントリーポイントを/usr/sbin/apache2に設定して、Apacheサーバが実行されるようにします。
さて、先ほど作成したDockerfileを使ってコンテナを構築し、その上にWebサイトを追加していきます。
そのためには、以下のコマンドを実行します。
docker build -t application .
以下のような出力が表示されるはずです。
shell Sending build context to Docker daemon 71.68kB Step 1/6 : FROM ubuntu-apache ---> 6997db13c658 Step 2/6 : ADD application.tar /tmp/ ---> 9b20f474c3a0 Step 3/6 : RUN mv /tmp/application/* /var/www/html/ ---> Running in 6f0b4a29cc8a ---> a5ffa4710b58 Removing intermediate container 6f0b4a29cc8a Step 4/6 : EXPOSE 80 ---> Running in e4ef5dfc0838 ---> a584d0068bb6 Removing intermediate container e4ef5dfc0838 Step 5/6 : ENTRYPOINT /usr/sbin/apache2ctl ---> Running in ab5bda3f593a ---> 65f187a34ce6 Removing intermediate container ab5bda3f593a Step 6/6 : CMD -D FOREGROUND ---> Running in b8ddd1d006b5 ---> 354383fb2666 Removing intermediate container b8ddd1d006b5 Successfully built 354383fb2666 Successfully tagged application:latestイメージが構築できたら、その上でApacheのインスタンスを実行するコンテナを作成して進めます。
docker run -d -P application
出力します。
a749b23fb87c821b69479353bf067f2b1af53fd0fd300ad86ac5c028dd5dcbde
さて、"docker ps "コマンドを使用してアクティブ化されたポートを判断し、curlを使用してサンプルの内容を検査します。
docker ps
以下のような出力が表示されるはずです。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a749b23fb87c application "/usr/sbin/apache2..." 30 seconds ago Up 28 seconds 0.0.0.0:32768->80/tcp nifty_boseここで、以下のコマンドを実行してApache Webサーバを確認します。
curl localhost:32768
または
curl "Container IP Address”:80
先ほど作成したApacheのWebページが表示されているはずです。
html <html> Sample Apache Web Page </html>Dockerコマンドを使った作業
まずはDockerが持っているすべての利用可能なコマンドを見てみましょう。以下のコマンドを実行することで、利用可能なDockerコマンドをすべて一覧表示することができます。
docker
Dockerのバージョンを確認するには、実行します。
docker version
出力します。
Client: Version: 17.09.0-ce API version: 1.32 Go version: go1.8.3 Git commit: afdb6d4 Built: Tue Sep 26 22:42:18 2017 OS/Arch: linux/amd64 Server: Version: 17.09.0-ce API version: 1.32 (minimum version 1.12) Go version: go1.8.3 Git commit: afdb6d4 Built: Tue Sep 26 22:40:56 2017 OS/Arch: linux/amd64 Experimental: falseDockerのシステム全体の情報を確認するには、実行します。
docker info
以下のような出力が表示されるはずです。
Containers: 2 Running: 1 Paused: 0 Stopped: 1 Images: 2 Server Version: 17.09.0-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実行中のコンテナをすべてリストアップするには、実行します。
docker ps
作成した最新のコンテナを一覧表示するには、実行します。
docker ps -l
実行中のコンテナと実行していないコンテナの両方をリストアップするには、実行します。
docker ps -a
コンテナのプロセスを起動・停止するには、以下のように実行します。
docker start "Container ID”
docker stop "Container ID"実行中のコンテナをすべて停止するには、実行します。
docker stop $(docker ps -a -q)
注: コンテナIDはsudo docker psコマンドを使って調べられます。
実行中のコンテナにアタッチしたい場合、Dockerではattachコマンドを使って実行中のコンテナと対話することができます。
docker attach "Container ID”
コンテナIDを指定したexpectコマンドを使うと、Dockerコンテナに関するあらゆる情報を確認することができます。
docker inspect "Container ID”
単一のコンテナを削除するには、実行します。
docker rm "Container ID”
既存のコンテナをすべて削除するには、実行します。
docker rm $(docker ps -a -q)
注: コンテナを削除する前に、まずコンテナを停止する必要があります。
1つのイメージを削除するには、image IDを指定してrmiコマンドを使用します。イメージIDは "docker images "コマンドを使って取得できます。
docker rmi "Image ID”
既存のイメージをすべて削除するには、実行します。
docker rmi $(docker images -q -a)
Dockerコンテナをデーモンとして実行している場合、実行中のコンテナのコンソール出力に何が表示されるかを知っておくと便利かもしれません。
Docker logsコマンドは実行時に存在するログを取得します。
コンテナIDを指定してDocker logコマンドを使うことができます。
docker log -f "container ID”
結論
おめでとうございます。これでDockerのインストールと実行が完了しました。これで、本番環境でDockerコンテナをインストールして使うための知識が十分に身についたと思います。Dockerの詳細については、Dockerの公式ドキュメントページを参照してください。その他のチュートリアルは、Alibaba Cloud Getting Startedチャンネルにも掲載されています。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-07-08T07:49:50+09:00
Dockerってなに?
はじめに
僕自身「Dockerってよく聞くけどなんのこと?」状態だったので気になって調べてみました。
仮想化とは
Dockerに触れる前に必要な知識として仮想化について簡単に説明します。
仮想化とは物理的な1台のサーバー上で、複数の仮想的なサーバー(仮想サーバー)を運用することを「サーバーの仮想化」といいます。簡単に例えると、windowsのpcで macのosを使えるようになりますよ みたいな
Docker
Dockerはこの仮想化を実現するための技術の一つです。
従来の仮想化技術(ホスト型 、 ハイパーバイザー型)では
1つのアプリケーションを起動するのに、1つのosを立ち上げていたため、起動に時間がかかるなどのデメリットがありました。~従来イメージ~
A家の中にもうひとつ別のB家を建てて、B家のキッチンで料理する
ですがDockerはアプリケーション単位で仮想環境を切り替えるので従来のデメリットを打ち消すことができます。
~Dockerイメージ~
A家の中にもうひとつ新しいキッチンを作り料理する
Dockerのメリット
①環境構築が簡単
②立ち上げ速度がはやい
③ハードウェアの資源削減
などが挙げられます。まとめ
仮想の中での話なのでイメージしづらいですね。
今後もDockerが普及し続けることが予想されますのでしっかり理解していきたいですね。
- 投稿日:2020-07-08T01:12:09+09:00
DockerでGolangをサクッと動かす
はじめに
ちょっとGolangを触ってみたくなったけど、
どう環境構築するのがいいのか考えるのがめんどくさかったり(当時はGOPATHってなに?って感じだった)
下手なことしてローカル環境汚すのがやだなぁとか思って、Dockerで動かしてみた時のメモ前提として、Docker, docker-composeは動かせること
docker run
コマンドのオプションをつらつらとかきたくなかったのでdocker-composeを使ってるディレクトリ構成とファイル作成
下記のようなディレクトリ構成でファイル作成
. ├── Dockerfile ├── docker-compose.yml └── workspace └── main.goDockerfileとdocker-composeは以下のような感じ
FROM golang:1.14.2 WORKDIR /go/src/workspace(当時A Tour of Goをやろうかなとか思ってたので
tour
)docker-compose.ymlversion: '3' services: tour: build: . tty: true volumes: - .:/go/srcmain.goではとりあえずHello Worldしてみる
main.gopackage main import "fmt" func main() { fmt.Println("Hello World") }動かし方
% docker-compose up -d Creating network "go_default" with the default driver Creating go_tour_1 ... done % docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 179cce348068 go_tour "bash" 40 seconds ago Up 38 seconds go_tour_1 % docker-compose exec tour go run main.go Hello Worldファイルはマウントしてるのでコンテナの外から
main.go
を好きにいじって保存すればそのままコンテナにも反映されてRunしなおせる
もちろんdocker-compose exec tour bash
とかでコンテナに入っても良し※ここではしてないが、Golangはコンパイラ言語なので基本的には
go build
でコンパイルするものさいごに
これすらもめんどくさい時はPlaygroundを使おう
- 投稿日:2020-07-08T00:56:33+09:00
ローカルでも CI でも使える卒論ビルド環境
TL;DR
ローカルビルドにも CI にも使える卒論 LaTeX のビルド環境を作った
概要
卒論を LaTeX で書くことになったが、環境構築を複数のマシンでするのがつらく、CI の自動ビルドを構築するのもつらい。Docker とビルドスクリプトで両方なんとかならないか考えていたらなんとかなったのでいくつか考慮するポイントを書き残しておく。
ソースコード
ローカルのビルドにも利用でき、実際に CI も走っているリポジトリ。プレビューは
preview
ブランチ。できること
- ローカルで
docker-compose up
するだけで論文がビルドできる- GitHub にプッシュすればローカルと同じビルド環境で勝手に CI してくれて
preview
ブランチの PDF が更新されるdevcontainer
にも対応しているのでビルド環境のシェルでゴニョゴニョできる (devcontainer
の起動のために VSCode が必要)解説
CI は GitHub Actions で構築するが、 Actions では任意の Docker イメージ上で作業できるため、基本的には:
- ビルド環境の Docker イメージ
- 上のイメージ上で正しく動作するビルドスクリプト
の2つが用意できればローカルでのビルド・CI での自動ビルドどちらも同じ環境で実行できる。
ビルドスクリプト
以下の2点に気をつける:
PDF ファイルの出力先を指定できるようにする
大抵は
.tex
ファイルのあるディレクトリでビルドスクリプトを叩くとそのディレクトリに例えば、
Makefile
なら:# paper-env/src/Makefile # command LATEX = platex DVIPDF = dvipdfmx ... # files TARGET = paper SRC = $(TARGET).tex DVI = $(TARGET).dvi PDF = $(TARGET).pdf ... # output directory OUT_DIR = $(TARGET).pdf $(PDF): $(DVI) $(DVIPDF) -o $(OUT_DIR) $< ...そして、実行時に
$ make OUT_DIR=[output directory]/paper.pdfとする。
GITHUB_WORKSPACE
環境変数に対応するGitHub Actions での CI の際、checkout されたリポジトリが格納されたディレクトリを
GITHUB_WORKSPACE
環境変数として渡してくれる:もし、ビルドスクリプト内で絶対パスを用いる必要がある場合は、この環境変数に対応する必要がある。
Docker, Docker Compose
ビルド環境を Docker イメージとして固めておけば良い。 Docker Hub でも GitHub Packages でもどちらに置いてもイメージのプルにかかる時間はあまり変わらなかったので、ここはログインなしでもプルできる Docker Hub がおすすめ。 (GitHub Packages はなんでパブリックイメージのプルにもログインが必要なんですか…?)
LaTeX
やpandoc
を扱えるイメージはたくさん転がっているため、それらを使っても良いし、自分の都合に合わせて作っても良いと思う。私のビルド環境イメージはこれ:実行時は、生の
docker
コマンドを叩いても良いが、ディレクトリのマウントやコマンドの指定が面倒なのでdocker-compose.yml
を書いておくと楽:# paper-env/docker-compose.yml version: "3" services: texlive: image: sarisia/texlive:2019 volumes: - .:/workspace:cached working_dir: /workspace entrypoint: [] command: [ "make" ]
- ワーキングディレクトリをマウントする
entrypoint
を指定するデフォルトでは、
Dockerfile
のENTRYPOINT
,CMD
が使われる。また、Dockerfile
は親イメージのENTRYPOINT
とCMD
を継承する。docker-compose.yml
でcommand
だけ指定した場合、もし変なENTRYPOINT
がDockerfile
やその親イメージで指定されていた場合、おかしな動きをする場合があるため、entrypoint
を指定してクリアしておくと安心。ビルドスクリプトの起動は
command
で指定する後述の
devcontainer
対応の際、devcontainer
のdocker-compose.yml
ではcommand
をオーバーライドしてコンテナが即死しないようにしているため、entrypoint
でビルドスクリプトの起動を指定してしまうとcommand
がentrypoint
の引数として解釈されてコンテナは死ぬ。これで、ローカルでビルドするときは:
$ docker-compose upするだけでビルドできるようになった。
CI (GitHub Actions)
GitHub にプッシュしたら勝手に PDF にしてどこかに置いておいて欲しい。
GitHub Actions は Docker イメージをアクションとして実行できる。ビルドスクリプトや Docker メージを使い回せるので最高。
アクション
以下の注意点に従い、
Dockerfile
とaction.yml
を用意する:Dockerfile support for GitHub Actions
# paper-env/.github/actions/latex-ci/Dockerfile FROM sarisia/texlive:2019 ENTRYPOINT [ "make" ]ビルドスクリプトの実行は
ENTRYPOINT
で指定すると良い。ENTRYPOINT
をオーバーライドするとCMD
もリセットされるため、おかしな引数が混入することもない。# paper-env/.github/actions/latex-ci/action.yml name: "latex ci" description: "build latex documents" runs: using: "docker" image: "Dockerfile"
GitHub Actions は、勝手にディレクトリをマウントし、そのディレクトリをワーキングディレクトリに指定しつつ
docker run
してくれる。ワークフロー
次に、アクションを利用するワークフローを定義する:
Workflow syntax for GitHub Actions
# paper-env/.github/workflows/preview.yml name: preview on: push: branches: - "master" tags-ignore: - "**" jobs: preview: name: preview runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: build documents uses: ./.github/actions/latex-ci - name: deploy to preview branch uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./preview publish_branch: preview keep_files: true commit_message: "preview:" - name: post status to discord uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK }} status: ${{ job.status }} job: deploy paper preview
actions/checkout
と./.github/actions/latex-ci
さえ忘れなければあとは自由。今回は別ブランチへのコミットとビルド結果の Discord への通知を行っている。
devcontainer
Docker コンテナを作業環境として使えるようにする。いちいち
docker exec
やdocker attach
とかしなくてもVisual Studio Code
ならワンクリックで起動できる。そうじゃなくても頑張って起動はできるのでファイルを置いておいて損はないと思う。Developing inside a Container using Visual Studio Code Remote Development
基本的には VSCode が勝手に自動生成してくれるファイルそのままで動く:
devcontainer/docker-compose.yml
VSCode 外で頑張って起動したいなら:
$ docker-compose -f docker-compose.yml -f .devcontainer/docker-compose.yml up -d $ docker-compose exec texlive /bin/bashまとめ
今の所は特にストレス無く使えている。
Overleaf や Cloud LaTeX などのオンライン IDE 環境もあるが、コンパイラが制限されていたり UI が煩雑だったりとあまり心地よくなかったので環境が落ち着いてよかった。
GitHub の Codespaces がリリースされれば、 Web エディタや VSCode からのリモート接続もできるようになるので、ローカルへのクローンすら不要になる。楽しみですね。
- 投稿日:2020-07-08T00:03:01+09:00
Stack Overflow Developer Survey 2020の要点整理
この記事の目的
世界のディベロッパーのトレンドを追う上で、非常に重要な資料であるStack Overflow Developer Surveyの最新版である2020年版の要点を整理すること。自分の理解のためだけでなく、毎年出されているにもかかわらず、日本語での情報共有が少ない本調査の要点を日本語で整理することで、多くの日本人の開発者が世界のトレンドを理解することを期待する。
原文
https://insights.stackoverflow.com/survey/2020調査概要
・2020年2月に世界中の65,000人以上のディベロッパーにアンケートを実施(注:回答者はアメリカ、インド、ヨーロッパに集中)。
・コロナウイルスが流行る前に調査が実施されたため、仕事や賃金のデータは現時点での情報と異なる可能性があることに注意。キーポイント
(1)最も愛された言語はRust, Typescript, Pythonの順番。Rustは五年連続で一位。
(2)回答者の8割がDevOpsが重要だと考えている。
(3)回答者の9割が、プログラミングで壁に当たった時、Stack Overflowを参照している。職種
・複数回答ありで、55%がバックエンド、フルスタックと答え、37%がフロントエンドのエンジニアと回答。
・プログラミング経験年数の層の中で一番高い割合が5年から9年で回答者の30%を占めた。5年以下と答えたのは17%。
・一方で、仕事としてプログラミングした経験は5年以下が最多で回答者の40%を占めた。
・回答者の85%は10代でプログラミングを開始した。学歴
・46%が学士号を、23%が修士号を取得。また回答者の6割以上が学部時代にコンピューターサイエンスを専攻していた。
言語その他のランキング