Dockerfileの置き場所・管理場所を色々考えた
- Dockerfileをどこに置いて誰が管理するのが良いのか?という話
- Dockerを導入する前の構成
- Docker導入初期
- 中央管理により発生する問題
- アプリケーションのレポジトリに置くことにする
- 今後
- まとめ
Dockerfileをどこに置いて誰が管理するのが良いのか?という話
結論から言うと、各アプリケーションのレポジトリ直下に置いて置けばいいのではないか、と言うのが現状。
そんなん当たり前だろと思った方はそのまま読み飛ばしていただいて、自分の思考の備忘もかねて。
チーム構成とか、開発やデプロイで使っているツールとか、アプリケーションの数でこの辺りの判断は変化しそうだけど、自分がインフラエンジニアの立場として考えていたことをまとめていく。
Dockerを導入する前の構成
Dockerを導入する前は、サーバーの構成管理をansibleで行なっていた。
そのため、すべてのアプリケーションの構成情報は一元管理されて一つのレポジトリでインフラエンジニアが管理する形だった。
Docker導入初期
Dockerを最初に導入した時にはansibleの構成をそのまま引き継ぐことに。
つまり、各Dockerfileを一元管理してインフラエンジニアが責任を持ってメンテナンスするところから始まった。
サーバーを作るのはインフラ側の仕事だし、突然構成管理をDockerfileで開始するからアプリケーション側で持ってね、って言ってもそれはただの無茶振りになる。
各アプリケーションが利用するフレームワークがRuby on Rails一つで、一種類のDockerfileで全部カバーできたと言うのも一つの理由。
また、Dockerの初期導入はテスト環境から始めることが多い気がするが、テストやビルドのスクリプト自体も自作して一元管理していたため、Dockerfileもその流れで一元化されたのは割と自然な流れだったと思う。
中央管理により発生する問題
Dockerfileの多様化
当初は一種類でまかなえていたDockerfileもアプリケーションが複雑化する中で多種多様になってくる。
そうなると色々な種類のDockerfileを用意する必要が出てくる。
特に最近はやりのマイクロサービスみたいな構成になってくると結構種類が増える。
インフラ作業が律速になる可能性
上記のような状態になると、XXXと言うミドルウェアを利用したい、とか、xxxという言語で次のアプリを書きたいと言った要望毎に、Dockerfileを更新する作業が発生する。
時間がある時にはいいのだが、障害続きのようなタイミングだと開発サイドを待たせてしまうことになりかねない。
アプリエンジニアのDocker知識がつかない
今後は、Dockerで開発をすることが当たり前になると思うので、組織としてレベルを上げるならこういった懸念も生まれる。
アプリケーションのレポジトリに置くことにする
といった流れで、アプリ側にDockerfileを置くことにした。めでたし。
デメリット
とはいえ、デメリットはそれなりにあると思っている。
各自が自由にできるので、、、
一番の心配はこれ。
今まで管理していたOSやパッケージ周りを手放す不安。
まあでもこれは大丈夫。
開発サイドとよっぽと仲悪くない限り。
Dockerfile編集したらpull requestこっちにもレビュー送ってねーとか、そういったコミュニケーションができていれば全く問題ないと思う。
まあそもそも専売特許でもないので、みんなで管理したらいいと思う。普通に。
重複部分が生まれる
Dockerfileが各所にあるのでどうしても重複する箇所が生まれる。
一斉に編集できない
OSやパッケージ周りで何か問題があった時に、全てのアプリのDockerfileを一斉に修正する手間が大きくなる。
ただし逆に言えば、影響範囲を最小限に抑えて段階リリースできると言うメリットとも言えるので、一長一短。
今後
重複部分が重なる問題に関して、ある程度のレイヤーまでは作られているDockerfileを一つ作ってもいいかなと言う気はしている。
少なくとも、OSと根本的なパッケージ、アプリを動かすユーザーとアプリを置くディレクトリくらいはよっぽどこのことがない限り一緒のはずなので、それは独立して一つ作っても良さそう。
各アプリはそれをFROMで指定してから、あとは自分たちのオリジナルの記述を書いていく形で。
まとめ
という感じで、アプリケーション側にDockerfileを置くことにした。
何より開発側のエンジニアが興味を持ってDockerについて聞いてきてくれたりするのが地味に嬉しかったりする。
RailsのDockerイメージを小さくしたい
- Docker imageを小さくする
- RailsのDockerイメージ
- 現状のDockerイメージ
- rbenvのinstallとrubyのinstallが無駄ではないか?
- ruby-alpineに変えてみる
- 結局何がサイズを大きくしてんの??
- Multi-Stage Buildsを使おう
- OSを変える
- いらなそうなファイルがないか探す
- とても大事なことに最後に気づく、、、
- まとめ
- ちなみに
Docker imageを小さくする
Dockerイメージは小さいほど良いです。これは自明です。
プログラムを動かすための必要最低限の実行ファイルがあれば良いのです。
RailsのDockerイメージ
そもそもバイナリだけで動くgoみたいな言語と違って、イメージが大きくなりがちなんですが
それでも多少は頑張りたいと思い試行錯誤してみる。
現状のDockerイメージ
Railsに関係する部分だけが削減対象かというとそうでもなく、
Dockerを導入し始めたばかりですのでイメージの最小化まで手がつけられていなかったのが現実で、基本的なところから色々と試して見ます。
今使っているDockerfileは恥ずかしながら、ansibleで実行しているコマンドをそのまま置き換えただけのものなので、インストーラなど実行ファイル以外のものがたくさん含まれています。
ubuntuのbase imageに
- apt-getで大量のパッケージを入れ
- rbenvをinstallし
- rubyの特定バージョンをinstallして
- bundle installする
という感じ。
一部省略していますが、Dockerfileは以下のようになっています。
/appというディレクトリの下に、sample(仮名)というソースを配置しています。
FROM ubuntu:trusty RUN apt-get update && \ apt-get -y install git curl make openssl zlib1g-dev libssl-dev libreadline-dev sysv-rc-conf build-essential mysql-client libmysqlclient-dev && \ mkdir -p /app && \ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv && \ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build && \ echo 'export PATH="~/.rbenv/bin:$PATH"' >> ~/.bashrc && \ echo 'eval "$(rbenv init -)"' >> ~/.bashrc && \ CONFIGURE_OPTS='--disable-install-rdoc' /root/.rbenv/bin/rbenv install 2.3.1 && \ /root/.rbenv/bin/rbenv global 2.3.1 ADD . /app/sample RUN /root/.rbenv/shims/gem install bundle && \ cd /app/sample && /root/.rbenv/shims/bundle install
なんとイメージサイズは892MBもありました。
rbenvのinstallとrubyのinstallが無駄ではないか?
そもそも真面目にDockerfile内でinstallしていることに疑問を持ち(インストール用に余計にパッケージが必要)、dockerhubからrubyのbaseimageを使ってみることにしました。
rubyが既に入っているので、それを入れるために必要だったのもを全て排除して見た結果のDockerfileがこちら。
FROM ruby:2.3.1 RUN mkdir -p /app ADD . /app/sample RUN cd /app/sample && /usr/local/bin/bundle install
なんとサイズが1.05GBGBに!なぜ増える!
ruby-alpineに変えてみる
よくよくみると、rubyのimage sizeが730MBもあることに気づきます。
結局rubyをinstallするために色々とパッケージを入れている模様。
ということで、127MBしかないruby-alpineを使ってみることに。
以下がDockerfile。alpineなので多少必要なパッケージを追加で入れています。
FROM ruby:2.3.1-alpine RUN apk add --update\ build-base \ git \ openssh \ mysql-dev \ linux-headers \ && \ mkdir -p /app RUN mkdir -p /app ADD . /app/sample RUN cd /app/sample && /usr/local/bin/bundle install
そしてイメージサイズは、857MB、、、あれ、、、、
結局何がサイズを大きくしてんの??
ruby:2.3.1-alpineのサイズ : 127MB
apk add した後 545MB
sample app ソースを追加した後 563MB
bundle install後 857MB
apk add と bundle installが大きい。まあ予想通り。
Multi-Stage Buildsを使おう
本題はここから。
Multi-Stage Buildsは、簡単にいうと、ビルド用のイメージを作った後に必要なファイルだけコピーして新しいデプロイ用などのイメージを作成できる機能です。
注) 諸々必要なものをinstallすると、ubuntuとalpineに大差がないと判明したので以後は何かと都合の良いubuntuで話を進めることに。
まず試したのは、今までのbuildイメージを先に作ってbundle installまでした後に、アプリのソース(/app以下)とruby(/root以下)のライブラリだけをコピーして来るパターン。
注2) Dockerfileを簡単にするために/rootにrbenv入れてますが本来は別ユーザー作ってそっちに入れた方がいいと思います。
FROM ubuntu:trusty as build-env RUN apt-get update && \ apt-get -y install git curl make openssl zlib1g-dev libssl-dev libreadline-dev sysv-rc-conf build-essential mysql-client libmysqlclient-dev && \ mkdir -p /app && \ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv && \ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build && \ echo 'export PATH="~/.rbenv/bin:$PATH"' >> ~/.bashrc && \ echo 'eval "$(rbenv init -)"' >> ~/.bashrc && \ CONFIGURE_OPTS='--disable-install-rdoc' /root/.rbenv/bin/rbenv install 2.3.1 && \ /root/.rbenv/bin/rbenv global 2.3.1 ADD . /app/sample RUN echo 'gem: --no-rdoc --no-ri' > /root/.gemrc && \ /root/.rbenv/shims/gem install bundle && \ cd /app/sample && /root/.rbenv/shims/bundle install FROM ubuntu:trusty RUN apt-get update && \ apt-get -y install mysql-client COPY --from=build-env /root /root COPY --from=build-env /app /app
mysql-clientだけ必要だったのでそれは追加。
これでイメージサイズが727MBに!
元々が892MBだったので165Mも削減!
こっそり.gemrc追加しましたが、これは1MBくらいしか削減効果ありませんでした。
OSを変える
Dockerfileを眺めていてふと気づく。
ubuntuが古い。
試しに、ubuntu:zestyをdocker pullしてみると、trustyよりもサイズが小さい!
昔誰かに、ubuntuを使っているならとりあえずdebianに変えて見たらdockerイメージが小さくなるよって言われたのを思い出しましたが、
debianのイメージサイズよりもubuntu:zestyの方が小さいようです。
ということで書き換え。
FROM ubuntu:zesty as build-env RUN apt-get update && \ apt-get -y install git curl make openssl zlib1g-dev libssl-dev libreadline-dev build-essential mysql-client libmysqlclient-dev && \ mkdir -p /app && \ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv && \ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build && \ echo 'export PATH="~/.rbenv/bin:$PATH"' >> ~/.bashrc && \ echo 'eval "$(rbenv init -)"' >> ~/.bashrc && \ CONFIGURE_OPTS='--disable-install-rdoc' /root/.rbenv/bin/rbenv install 2.3.1 && \ /root/.rbenv/bin/rbenv global 2.3.1 ADD . /app/sample RUN echo 'gem: --no-rdoc --no-ri' > /root/.gemrc && \ /root/.rbenv/shims/gem install bundle && \ cd /app/sample && /root/.rbenv/shims/bundle install FROM ubuntu:zesty RUN apt-get update && \ apt-get -y install tzdata openssl libmysqlclient-dev COPY --from=build-env /root /root COPY --from=build-env /app /app
多少必要なパッケージが変わったのでapt-getの部分を少し修正。
イメージサイズは614MBに!
OSを変えるだけでこんなに変わるとは、、、
いらなそうなファイルがないか探す
あんまりなさそうだったが、この辺は要らないので Dockerfileの最後にこれを追加。
bundle install後にできるgemsの中身はもっとせめて消せそうなものがありそうだけど、攻めすぎて壊しそうなので一旦断念。
c extensionを含むgemが割とサイズが大きそうで、実行ファイル以外消したらもうちょと小さくなりそうだけど、ROI低そうな感じがした。
RUN rm -fr /var/lib/apt/lists/*.lz4 && \ rm -fr ~/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/cache/*
これを消してもそこまで小さくならず、613MBに。
とても大事なことに最後に気づく、、、
配布用のイメージなので、bundle installは --without development test をつけてあげないとダメでした。。。
ということで最終的には、547MBになりました。
gemの削減が一番効果あるな、これは、、、
892MB => 547MB なので 345MBの削減になりました!
まとめ
- Multi-Stage Buildsは使った方がいい
- alpineとかじゃなくてもOS変えるだけでイメージ小さくなることがある
- 使わないgemとかバンバン消していきましょう!
仮想通貨(暗号通貨)をGPUマイニングするためのスターターキット
仮想通貨(暗号通貨)マイニングとは?
ここにたどり着いた方であればこの説明は不要かと思いますので割愛。
仮想通貨マインングセットを組み立てる用事があったのでまとめとして記事にします。
これからマイニングリグを自前で作る方の参考になればと思います。
基本的に全てのパーツはAmazonで購入可能なので商品リンクもつけておきますが、秋葉などの店頭割引セールで買った方が安い場合もあります。
[注意] 自前でマイニングキットを用意するためには最低でも15万円程度の初期投資が必要になります。
もし、もう少し初期投資を抑えたいという方はクラウドマイニングをオススメします。
kenjiszk.hatenablog.com
ということで必要パーツの紹介です。
必要パーツ
GPU(グラフィックカード)
何は無くともGPUは必要。今回はNVIDIA GIGABYTE GTX 1070を購入。
グラフィックカードはついこの間まではかなり安かった気がしますが、17年夏あたりのイーサリアムの高騰で一気に値段があがりました。
在庫もほとんどのお店で数個しかないのではないかと思います。
どのグラボを購入すれば良いかはこちらのサイトを参考にしたら良いと思いますが、店頭で買う場合には結構店員さんが詳しいので聞いてしまうのもあり。
whattomine.com
マザーボード
マイニング専用のマザーボードが販売しています。具体的には、グラフィックカードが何枚もさせるように、PCI-Eの拡張ポートがいくつもあるやつです。
準備できる電源によって何枚使えるかは決まりますが、6枚 ~ 12枚くらいの種類があるようです。
ライザーケーブル
グラフィックボード何枚も指す関係で、マザーボードに直挿ししないのでグラフィックボードとマザーボードを接続するためのケーブルが必要になります。
何枚もグラボを購入するならまとめ買いがお得。
ちなみにググった感じかなりこのケーブルは壊れやすいそう。
電源
上記で購入したGTX 1070の場合、直接の電源供給口から最大で150W, ライザーケーブルから最大75W供給がされるそうなので、一枚で225Wを最大で利用する計算になります。
例えば、GTX1070 6枚を利用するなら、750Wの電源を二つ用意すると良さそうです。
上記の数字はmax値なのでおそらくもう少し低くても動作する可能性はありますが、電源をケチると火事になる可能性すらあるので注意したいところ。
ググるとマイニング工場の火事の記事がたくさん出てきますw
性能の一つの指標として、電力変換効率の性能別にSTANDARD、BRONZE、SILVER、GOLD、PLATINUM、TITANIUMという指標があるが、予算に余裕があるならより良いものを買う方が良いと思われる。
電源を2つ利用する場合
電源同士の同期をしないといけないので、このパーツが必要になる。
CPU/メモリ
この二つはマイニングリグを作るときには性能を求められないので、売っている一番安いのを購入したら良い。
windowsは4Gくらいメモリがないと安定しないのでメモリは4Gくらいのものを選んでおけば良い。
OS
グラフィックカードのドライバーがwindowsの方が性能が良いと聞いたのでwindowsを購入してみましたが、
知人はlinuxでも安定して動いていると言っていたのでそこは好みで。
ちなみに、Proだと windows updateを設定で停止できるので proを買えばwindows updateが急に走ってマイニングが止まっていたなんてことにはならないとのこと。
[asin:B0772WPC8H:detail]
組み立てハマりどころ
正直そこまで組み立てでハマるところはないです。
一点だけ、マイニングラックを買わずに普通のラックを購入した場合、マザーボードに刺すようのPCのリセットボタンがないと思うので
それだけ別途購入する必要が出てきます。
どのコインを掘る?
これはさっきも紹介したこのサイトで簡単に選定できます。
whattomine.com
今回購入しているGTX 1070を洗濯した後に
計算ボタンを押すとこんな感じで各コインのマイニング効率が出てきます。
ここで出てきた効率良さそうなコインでマイニングソフトが手に入るものを掘るのがいいのではないかと思います!
まとめ
簡単でしたがスターターキットの紹介でした。
Happy Mining!
そういえば去年掘ったあれ、今いくらになってんの?
最近はビットコインやらマイニングやら流行っておりますが、そう言えば去年マインングにチャレンジしていました。
この記事で試しに掘ったBytecoinの件ですね。
qiita.com
去年のスクショがこちら。
はい、そのまま放置していましたが、これが今年のスクショ。
当然、放置していたのでコインの枚数は変わりませんが、、、
0.00038125 EUR => 0.01301568 EUR
おっ??
1年間でコインの価値が上がったようですね。
1年前にこの発言をしている自分を責めたい
1ヶ月に換算したら10ユーロ近いよ!全然ペイしてるよ!
このサーバー 一ヶ月0.66ユーロだからね!
ということで、将来性を見抜けなかった自分の負けですね。
そのまま掘り続けていれば、単純計算で120ユーロくらいになっていたようです。
一般的なエンジニアスキルにも言えますが、
将来流行るであろう技術を如何に先攻して習得していくかどうかってのが鍵なんだろうなー。
複数のRDSから1台のEC2にレプリケーションをする方法 複数MySQL編
以前こんな記事を書きましたが、もうちょっといい方法を思いついたので更新。
qiita.com
そもそもマルチソースレプリケーションが辛いところ
MySQLがトラブると全部アプリケーションのレプリが止まる
レプリケーション元が大量にある場合、セットアップだけでも結構な時間を要する。
せっかく設定が終わったのに、その段階でMySQLレイヤーでのトラブルが起ると辛い。MySQLがstopもしくはクラッシュしてデータが壊れた場合、全ての設定をやり直す羽目になる。
一つだけ止めるといったことができない
MySQLのパラメータを更新したい場合がある。オンラインで変更可能なものもあるが、MySQLの再起動を必要とするものもある。
全てのデータベースが一つのMySQLに乗っていると、MySQLのstop/startの作業とパラメータの反映も全てのデータベースに波及する。
全部同じMySQLのバージョンとパラメータで起動する
アプリケーションによってはMySQLのバージョンが違ったり、パラメータを変えたかったりするかもしれない。
そういったことは、マルチソースレプリケーションでレプリケーションをうけるのは不可能になる。
レプリケーションのCHANNEL管理
10個くらいチャンネルが増えてくると結構めんどくさいことに。
たまーにレプリケーションが止まった時に、エラーになったクエリだけskipしたかったりするのだけど、channel対応していないコマンド(変数)があるとかなり管理が面倒になる。
SQL_SLAVE_SKIP_COUNTERとか。
Auroraが5.7ベースではない
マルチソースレプリケーションはMySQLの5.7からサポートされている機能だが、レプリケーション元としてAWS Auroraを利用している場合バージョンの不一致が起きる。
データを閲覧するだけであれば実際に大きな影響はないのだが、index系の調査でEXPLAINを打って実行計画を確認したり、実際にindexを貼ってみてクエリのパフォーマンス改善具合を確かめる時にオプティマイザの挙動が異なるために望んだ結果が得られない場合がある。
実際に、slaveでは問題なくindexが効くのに、実際のmasterのauroraでは早くならないという場面に出くわした。
ただし、JOINはできなくなる
1MySQL上に複数のデータベースがあることで解決する一つの問題はJOINができるということだと思う。
当然webアプリケーションのようにクエリのパフォーマンスが求められるところでは使うことはないとは思うが、分析などクエリのパフォーマンスを求めないようなところでは便利かもしれない。オススメはしない。
そこで、dockerによる複数MySQLの1台のEC2での起動を試してみた
docker-composeの利用
EC2上に複数のMySQLを立ち上げるために今回はdocker-composeを利用した。
設定をファイルに落としておけるのと、別EC2でもえいやっと一気にmysqlがたくさん上がってくれるため。
設定ファイルの例を以下に。各MySQLでポートだけずらしておき、my.cnfだけ外部ファイルを読むようにして修正可能にしている。
app1: image: mysql:5.6 volumes: - "./my.cnf.utf8mb4:/etc/my.cnf:ro" ports: - "13306:3306" environment: MYSQL_ROOT_PASSWORD: root app2: image: mysql:5.6 volumes: - "./my.cnf.utf8mb4:/etc/my.cnf:ro" ports: - "23306:3306" environment: MYSQL_ROOT_PASSWORD: root app3: image: mysql:5.6 volumes: - "./my.cnf.utf8mb4:/etc/my.cnf:ro" ports: - "33306:3306" environment: MYSQL_ROOT_PASSWORD: root
Auroraからのレプリケーション設定
このページが詳しいので割愛
docs.aws.amazon.com
課題
JOIN問題
各MySQLが別ホスト(別docker)になるのでJOINはできなくなる。
負荷問題
MySQLは別れたが、OSは同一のものを使っているのでマシンが落ちたらそれは全滅。
AWS Auroraの機能拡張
こんな機能があればAuroraだけで完結できるので、AWSさんよろしくお願いします。
あらゆるインフラの足回りをフルマーネージドで完結させたい!!
Auroraのクラスタ内で、readのendpointからは参照がこないようなreaderの作成
書き込みが可能なレプリカ
もう一つの要件として、分析用途などでは必要のないデータのマスキングをしたいという要望がある。
現時点ではレプリカに対して書き込みを行うとエラーになるので、特定のフラグが立っているレプリカだけ書き込みも許可できるようなると嬉しい。
しかし、RDSやAuroraを使い始めてからあんまりMySQLのコアな機能の詳細を追わなくなってきた感があるなあ。。
ロボットアドバイザー THEO を1年半試してみた結果
簡単に個人投資が出来るロボットアドバイザーTHEOって?
theo.blue
お金を預けて簡単なポートフォリオを設定しておくと、THEOのシステムが勝手に運用してくれるというサービス。
投資に詳しくなくても資産運用ができるというもの。
特徴は、日本円で資産を持っているリスクに対して、国際分散投資という方式を提案しているところ。
どのくらい儲かるのか?
結果を晒してみる。
1年半で+17.97%という結果に。
最初の半年間はずっとマイナスで遷移していたので、まじかい、と思っていたがその後はあれよあれよと上り調子に。
長期的な投資としてどーんと構えているのが良さそう。
ちなみに、最初の半年間はずっと円高だった為だと思われる。
その後の成長はトランプが大統領になったくらいのタイミングからでアメリカ株が好調だった為かなーと。
1年半でやった事
半年後に追加資金を投入
THEOは基本的に、日本円で持つ事をリスクと考えて海外株に投資するというスタンスなので
円高の底かなあと思ったタイミングで追加で資金を投入してみた。
運良くその読みは当たり、その後プラス転向してくれた。
(ホントはもっといろんな要因がありそうなので運がよかっただけかも?)
感想と今後
年率10%強くらいで利益をだせているので今のところ満足。
今後も定期的に資金は追加していきたいところだが、また円高になったタイミングで突っ込もうかなと思う。
最安VPS Time4VPSが安すぎた
VPS 月額0.66ユーロ
ちょっとした用事でサーバーが必要だったので安いVPSを探していたら、Time4VPSというVPSが月0.66ユーロ(約80円)という驚きの価格を提供していたので、まあ駄目元で契約してみた。
ちなみにスペックは、CPU 1 x 2.40 GHz、メモリ 512 MB、ディスク 20 GB。凄い時代だ、、、。
購入からログインまで一瞬
サインアップ後に、サーバー購入画面に進みPaypalで購入。10分もするとアクセス可能なサーバーが用意されていた。支払方法はクレジットカードでも大丈夫。
OSも標準的なものは選べるようで、今回は普段使っているubuntuにしてみた。
スペックなど
ちょっとしたjobを走らせて見ている感じ、そんなに遅い感じもしないがこれは継続的に使ってみないとちょっと分からないかなという感じ。今の所全く不満はない。
CPU4コアのメモリ8Gまでスペックがあるので、個人レベルでは十分。