Let's Encryptで証明書を取ってみた(DockerのNginXコンテナ(Alpine)から)

 タイトルの通り、Let's Encryptで証明書を取ってみた。DockerのNginXコンテナ(Alpine)から。メモ。ちなみにHyper.shでコンテナのホスティングは行っている。なのでコンテナを動かすコマンド体系はHyper.sh準拠。ほぼDockerコマンドのまんま。

 まずコンテナを用意。
hyper run -d --name foo -p 80:80 -p 443:443 nginx:alpine


 IPをつける。DNS設定はしてあるものとする。
hyper fip attach xxx.xxx.xxx.xxx foo


 NginXコンテナが動いていて、そこへDNS設定してあるIPをつけたのだからアクセスできるはず。URLを入れてアクセスできるか確認しておく。



 コンテナへ入る。
hyper exec -it foo /bin/sh


 認証を実行してくれるライブラリを入れる。
apk update

apk add certbot


 下記でヘルプが表示される。
certbot -h


 すでにこのコンテナではNginXが動いている。デフォルトの設定で。だからcertbotには、NginXを使った認証コマンドを実行してもらう。
certbot certonly --webroot -w /usr/share/nginx/html -d hmatoba.net

これでインストラクションに従って入力していくだけ。成功すれば発行されたというメッセージとともにファイルが出力される。


 自動化のために、インストラクションで進める形はやめて、オプションを与えていかなければならない。しかしまあ証明書は取れた。めでたしめでたし。
comment: 0

C#でMongoDBでのサーバーサイドJavaScriptを実行する

 コレクションの集計処理をしたかったのだが、MapReduceでは望みの形に集計結果をまとめられなかった。だからサーバーサイドJavaScriptでやることにした。ただしサーバーサイドJavaScriptはセキュリティの懸念やパフォーマンスの注意点があるので気軽に使うものではない。今回はそれらが問題として出てこないので使うことにした。

 まずC#コード。サーバーサイドで実行するJavaScriptも埋め込んだ。
//using MongoDB.Driver;

//using MongoDB.Bson;
//using MongoDB.Driver.Core.Operations;
//using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
//using MongoDB.Driver.Core.Bindings;
//using System.Threading;

class Program
{
private static IMongoClient client;
private static IMongoDatabase DbConnection;

static void Main(string[] args)
{
client = new MongoClient("mongodb://127.0.0.1");
DbConnection = client.GetDatabase("helicon");

AggregateTag();
}

public static void AggregateTag()
{
var databaseName = new DatabaseNamespace("helicon");

var code = (BsonJavaScript)@"
function () {
// do something
}";

var messageEncodingSettings = new MessageEncoderSettings();
var operation = new EvalOperation(databaseName, code, messageEncodingSettings);
var source = new CancellationTokenSource();
var token = source.Token;
var writeBinding = new WritableServerBinding(client.Cluster);
operation.Execute(writeBinding, CancellationToken.None);
}
}


 あとはサーバサイドでJavaScriptを実行するために、接続ユーザに実行権限を持たせる。
Allow user to execute eval() command on MongoDB 3.x

データベースに管理権限者でログイン。そしてadminデータベースへ。
use admin;


ロールを作成。
db.createRole( { role: "executeFunctions", privileges: [ { resource: { anyResource: true }, actions: [ "anyAction" ] } ], roles: [] } )


ロールを接続ユーザに付加。
db.grantRolesToUser("someone", [ { role: "executeFunctions", db: "admin" } ])


付加されたことを確認。
db.getUser("someone") 


これで権限が付いたので、C#コードを実行すればMongoDBのサーバサイドJSが実行される。

 このブログのサイドバーの、タグや投稿月毎の記事のカウントにこの、MongoDBのサーバサイドJSを使っている。
comment: 0

Hyper.shでSSL接続するアプリの継続的デプロイ(まだ決定打なしのイマイチな方法)

 Dockerコンテナでアプリを運用したい場合、Hyper.shがイカす。そのHyper.shで、Let's encryptで取得する証明書を使ってHTTPSで接続できるようにしてみる。

Serviceを使う
→コンテナ立ち上げコマンドで証明書を引数として渡している。Let's encryptは証明書の有効期間が短いから自動更新を繰り返していきたいんだけど、そのたびにコンテナを立ち上げ直さなきゃならない?それをクリアできるならば一番いい方法

・アプリコンテナにリバースプロキシを入れてごにょごにょ
→アプリコンテナがちょいややこしくなるのと後述する理由でナシ

・アプリコンテナの外にリバースプロキシコンテナを用意して接続
https-portalという、超簡単にLet's encryptの証明書でSSLを使えるようにしてくれるコンテナがある。これを使って今回はやってみるが、結果は問題が残った。

 https-portalのGithubページのサンプルをちょっといじったdocker-compose.ymlを書く。
docker-compose.yml

version: '2'

services:
https-portal:
image: steveltn/https-portal:1
ports:
- '80:80'
- '443:443'
environment:
DOMAINS: 'example.com -> http://dncindocker'
STAGE: 'production'
FORCE_RENEW: 'true'
fip: xxx.xxx.xxx.xxx
dncindocker:
image: matoba/dncindocker:latest

 こいつをHyper.shへ。
hyper compose -up d -p foo

これで一分ほど待てばアプリのデプロイが完了するだろう。このコマンドに加えて下記のコマンドでプロジェクト消去コマンドがあれば、デプロイを容易にサイクル化できる。
hyper compose rm -v -p foo


 で、この方法はデプロイするたびにhttps-portalコンテナが証明書を取りに行く。これが問題となる。じっさいデプロイを何度も試しているうちに遭遇したのが、証明書の期間あたりの取得上限。変更がなければ週に20回までのようだ。これに達すれば証明書の発行はいったんストップするので、https-portalコンテナが正常な動作をしなくなる。そういうわけで、https-portalコンテナをデプロイの度に動かし直すのはよくない。コンテナのデプロイを分けなければならない。そうしたらそうしたで、デプロイの度にどうやってhttps-portalコンテナからアプリコンテナへの接続をやるかという課題が生まれる。
 そういうわけでLet's encrypt + 継続的デプロイのプロセスの確立に失敗した。

解決のために取るべき方法
・Serviceで証明書の自動更新と継続的デプロイができるか調査
・リバースプロキシコンテナとアプリコンテナをComposeで管理しない。リバースプロキシコンテナは動かしっぱなし、アプリコンテナだけを更新。走りっぱなしのリバースプロキシコンテナからアプリコンテナへの接続手段を得る。
comment: 0

TravisCIからHyper.shへDockerコンテナなアプリを継続的デプロイ

 Dockerコンテナなアプリをホビー用途でデプロイするならHyper.shがとてもイカしてる。そんなHyper.shとTravisCIを掛け合わせて継続的デプロイを組んでみる。

 このブログで、TravisCIから、テストにとおったアプリのDockerイメージを、継続的にDocker hubへプッシュしていくまではやっている。
.NET CoreのDockerコンテナに入ったWebアプリをTravisCIでCI
 今回はDocker hubへのプッシュ後に、Hyper.shのCLIツールをそのままTravisCIで使ってDockerコンテナを走らせるまで。

 まずHyper.shでアクセストークンとキートークンを発行し、TravisCIで環境変数にセット。




 続いて.travis.ymlにHyper.shのCLIツールでの処理(コンテナ立ち上げ)を追加。
.travis.yml

after_success:
- docker tag matoba/dncindocker:ci matoba/dncindocker:latest
- docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}"
- docker push matoba/dncindocker:latest
- wget https://hyper-install.s3.amazonaws.com/hyper-linux-x86_64.tar.gz
- tar xzf hyper-linux-x86_64.tar.gz
- ./hyper --help
- ./hyper config --accesskey ${HYPER_ACCESS} --secretkey ${HYPER_KEY}
- ./hyper run -d -p 80:80 --name mersault matoba/dncindocker:latest



 上記までで設定はOK。TravisCIでのテストを走らせる前、Hyper.shではコンテナやイメージはまだゼロ。



 TravisCIでのテストが通ったあとに見るとコンテナやイメージにカウントが増えている



 しっかりコンテナが動いている。



 IPを当ててブラウザでアクセスしてみる。



 管理コンソールを見ていると環境変数を入れるフォームはなさそう。そうなると環境変数を与えられるタイミングはコンテナを起動させるタイミングである。アプリで使われる環境変数はTravisCIに入れて運用していくことになるんかな。
comment: 0

Azure Web App on LinuxでDockerコンテナによるデプロイをしてみる

 前回でTravisCIからDocker hubへ、テストにとおったDockerイメージをプッシュした。これのデプロイ先としてAzure Web App on Linuxを選んだ場合をちょっとやってみる。

 AzureポータルでWeb App on Linuxを選び、イメージのソースをDocker hubに上げてあるイメージを指定。そして進む。


 デプロイが済むまでちょい待ってからアクセスしてみると、しっかりアプリが起動している。あれ?デプロイこんだけで済んじゃう?という感想。



 ところで、遊びに使うにはちょい高い。まあアプリケーションに注力するために、OSなどをよしなにやってくれるマネージドだからこんなところか。



 Docker hubとAzureの連携で継続的デプロイも可能。
Azure Web App on Linux での Docker Hub の継続的なデプロイ





comment: 0