20190530のdockerに関する記事は7件です。

一足遅れて Kubernetes を学び始める - 13. ヘルスチェックとコンテナライフサイクル -

ストーリー

  1. 一足遅れて Kubernetes を学び始める - 01. 環境選択編 -
  2. 一足遅れて Kubernetes を学び始める - 02. Docker For Mac -
  3. 一足遅れて Kubernetes を学び始める - 03. Raspberry Pi -
  4. 一足遅れて Kubernetes を学び始める - 04. kubectl -
  5. 一足遅れて Kubernetes を学び始める - 05. workloads その1 -
  6. 一足遅れて Kubernetes を学び始める - 06. workloads その2 -
  7. 一足遅れて Kubernetes を学び始める - 07. workloads その3 -
  8. 一足遅れて Kubernetes を学び始める - 08. discovery&LB その1 -
  9. 一足遅れて Kubernetes を学び始める - 09. discovery&LB その2 -
  10. 一足遅れて Kubernetes を学び始める - 10. config&storage その1 -
  11. 一足遅れて Kubernetes を学び始める - 11. config&storage その2 -
  12. 一足遅れて Kubernetes を学び始める - 12. リソース制限 -
  13. 一足遅れて Kubernetes を学び始める - 13. ヘルスチェックとコンテナライフサイクル -

前回

一足遅れて Kubernetes を学び始める - 12. リソース制限 -では、requestsやlimitなどのリソース制限について学習しました。今回は、ヘルスチェックとコンテナライフサイクルについて学習します。

ヘルスチェック

Kubernetesでは、Podの正常生判断のためのヘルスチェックが2種類用意されています。

  • Liveness Probe
    • Podが正常か判断。異常だった場合、Podを再起動。
  • Readiness Probe
    • Podがサービスインする準備ができているか判断。準備できていなかったら、トラフィックを流さない。

たとえば、Pod内でメモリリークが発生し応答しなくなった場合に有効です。
LoadBalancerのサービスは、ICMPによる簡易ヘルスチェックがデフォルトで用意されています。

また、Liveness、Readinessどちらにも3つの方式があります。

  • exec
    • コマンドを実行し、終了コードが0でなければ失敗
  • httpGet
    • HTTP GETリクエストを実行し、statusCodeが200~399でなければ失敗
  • tcpSocket
    • TCPセッションが確立できなければ失敗

では、試してみましょう。

sample-healthcheck.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-healthcheck
  labels:
    app: sample-app
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12
      ports:
      - containerPort: 80
      livenessProbe:
        httpGet:
          path: /index.html
          port: 80
          scheme: HTTP
        timeoutSeconds: 1
        successThreshold: 1
        failureThreshold: 2
        initialDelaySeconds: 5
        periodSeconds: 3
      readinessProbe:
        exec:
          command: ["ls", "/usr/share/nginx/html/50x.html"]
        timeoutSeconds: 1
        successThreshold: 2
        failureThreshold: 1
        initialDelaySeconds: 5
        periodSeconds: 3
  • timeoutSeconds
    • タイムアウトまでの秒数
  • successThreshold
    • 成功と判断するまでのチェック回数
  • failureThreshold
    • 失敗と判断するまでのチェック回数
  • initialDelaySeconds
    • 初回ヘルスチェック開始までの遅延
  • periodSeconds
    • ヘルスチェックの間隔
pi@raspi001:~/tmp $ k apply -f sample-healthcheck.yaml
pi@raspi001:~/tmp $ k describe pod sample-healthcheck | egrep "Liveness|Readiness"
    Liveness:       http-get http://:80/index.html delay=5s timeout=1s period=3s #success=1 #failure=2
    Readiness:      exec [ls /usr/share/nginx/html/50x.html] delay=5s timeout=1s period=3s #success=2 #failure=1

設定どおりに動作していますね。では、失敗させましょう。

livenessを失敗させるにはindex.htmlを削除すれば良いですね。

pi@raspi001:~/tmp $ k exec -it sample-healthcheck rm /usr/share/nginx/html/index.html
pi@raspi001:~/tmp $ k get pods --watch
NAME                                      READY   STATUS    RESTARTS   AGE
sample-healthcheck                        1/1     Running   1          9m54s
sample-healthcheck                        0/1     Running   2          10m
sample-healthcheck                        1/1     Running   2          10m

一度削除されて、再起動しましたね。
今度は、readinessを失敗させましょう。こちらは50x.htmlを削除すれば良いですね。

pi@raspi001:~/tmp $ k exec -it sample-healthcheck rm /usr/share/nginx/html/50x.html
pi@raspi001:~/tmp $ k get pods --watch
NAME                                      READY   STATUS    RESTARTS   AGE
sample-healthcheck                        1/1     Running   2          16m
sample-healthcheck                        0/1     Running   2          16m
pi@raspi001:~/tmp $ k exec -it sample-healthcheck touch /usr/share/nginx/html/50x.html
pi@raspi001:~/tmp $ k get pods --watch
NAME                                      READY   STATUS    RESTARTS   AGE
sample-healthcheck                        0/1     Running   2          17m
sample-healthcheck                        1/1     Running   2          17m

期待通り、50x.htmlを削除すると、READYから外れて、追加するとREADYに戻りました。

コンテナの再起動

コンテナのプロセスが停止、またはヘルスチェックの失敗によってコンテナを再起動するかどうかは、spec.restartPolicyによって決まります。
種類は下記3つです。

  • Always
    • 常にPodを再起動させる
  • OnFailure
    • 終了コード0以外の予期せぬ停止の場合、Podを再起動させる
  • Never
    • 再起動させない

試してみましょう。

sample-restart-always.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-restart-always
spec:
  restartPolicy: Always
  containers:
    - name: nginx-container
      image: nginx:1.12
      command: ["sh", "-c", "exit 0"] # 成功の場合
#      command: ["sh", "-c", "exit 1"] # 失敗の場合
pi@raspi001:~/tmp $ k apply -f sample-restart-always.yaml
# 成功の場合
pi@raspi001:~/tmp $ k get pods sample-restart-always --watch
NAME                    READY   STATUS              RESTARTS   AGE
sample-restart-always   0/1     ContainerCreating   0          13s
sample-restart-always   0/1     Completed           0          19s
sample-restart-always   0/1     Completed           1          27s
sample-restart-always   0/1     CrashLoopBackOff    1          28s
sample-restart-always   0/1     Completed           2          37s
# 失敗の場合
pi@raspi001:~/tmp $ k get pods sample-restart-always --watch
NAME                    READY   STATUS              RESTARTS   AGE
sample-restart-always   0/1     ContainerCreating   0          7s
sample-restart-always   0/1     Error               0          12s
sample-restart-always   0/1     Error               1          17s
sample-restart-always   0/1     CrashLoopBackOff    1          18s
sample-restart-always   0/1     Error               2          37s

成功、失敗どちらも再起動していることがわかります。

sample-restart-onfailure.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-restart-onfailure
spec:
  restartPolicy: OnFailure
  containers:
    - name: nginx-container
      image: nginx:1.12
      command: ["sh", "-c", "exit 0"] # 成功の場合
#      command: ["sh", "-c", "exit 1"] # 失敗の場合
pi@raspi001:~/tmp $ k apply -f sample-restart-onfailure.yaml
# 成功の場合
pi@raspi001:~/tmp $ k get pods sample-restart-onfailure --watch
NAME                       READY   STATUS              RESTARTS   AGE
sample-restart-onfailure   0/1     ContainerCreating   0          3s
sample-restart-onfailure   0/1     Completed           0          15s
# 失敗の場合
pi@raspi001:~/tmp $ k get pods sample-restart-onfailure --watch
NAME                       READY   STATUS              RESTARTS   AGE
sample-restart-onfailure   0/1     ContainerCreating   0          4s
sample-restart-onfailure   0/1     Error               0          22s
sample-restart-onfailure   0/1     Error               1          28s
sample-restart-onfailure   0/1     CrashLoopBackOff    1          29s
sample-restart-onfailure   0/1     Error               2          50s

成功時は、Completedの終了していますね。CrashLoopBackOffしていません。失敗時は、Errorとなり、CrashLoopBackOffしています。
期待通りですね。

initContainers

Podのメインとなるコンテナを起動する前に別のコンテナを起動させるための機能です。
spec.containersがもともとありますが、こちらは同時並列で起動するので、順序が必要な場合には向いていません。
initContainersは、spec.initContainersで設定でき、複数指定できます。複数の場合は上から順に起動します。

試してみましょう。

sample-initcontainer.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-initcontainer
spec:
  initContainers:
    - name: output-1
      image: nginx:1.12
      command: ['sh', '-c', 'sleep 20; echo 1st > /usr/share/nginx/html/index.html']
      volumeMounts:
      - name: html-volume
        mountPath: /usr/share/nginx/html/
    - name: output-2
      image: nginx:1.12
      command: ['sh', '-c', 'sleep 10; echo 2nd >> /usr/share/nginx/html/index.html']
      volumeMounts:
      - name: html-volume
        mountPath: /usr/share/nginx/html/
  containers:
    - name: nginx-container
      image: nginx:1.12
      volumeMounts:
      - name: html-volume
        mountPath: /usr/share/nginx/html/
  volumes:
  - name: html-volume
    emptyDir: {}
pi@raspi001:~/tmp $ k get pod sample-initcontainer --watch
NAME                   READY   STATUS     RESTARTS   AGE
sample-initcontainer   0/1     Init:0/2   0          3s
sample-initcontainer   0/1     Init:0/2   0          9s
sample-initcontainer   0/1     Init:1/2   0          30s
sample-initcontainer   0/1     Init:1/2   0          38s
sample-initcontainer   0/1     PodInitializing   0          51s
sample-initcontainer   1/1     Running           0          59s
pi@raspi001:~/tmp $ k exec -it sample-initcontainer cat /usr/share/nginx/html/index.html
1st
2nd

確かに、initContainersが順序通り起動できています。ふむふむ。

起動時と終了時のコマンド実行(postStart,preStop)

コンテナ起動後に実行するコマンドをpostStart,
コンテナ終了前に実行するコマンドをpreStopという機能で実現できます。

sample-lifecycle.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-lifecycle
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12
      command: ["/bin/sh", "-c", "touch /tmp/started; sleep 3600"]
      lifecycle:
        postStart:
          exec:
            command: ["/bin/sh", "-c", "sleep 20; touch /tmp/poststart"]
        preStop:
          exec:
            command: ["/bin/sh", "-c", "touch /tmp/prestop; sleep 20"]
pi@raspi001:~/tmp $  k apply -f sample-lifecycle.yaml
pi@raspi001:~/tmp $  k exec -it sample-lifecycle ls /tmp
started
# 数秒後
pi@raspi001:~/tmp $  $ k exec -it sample-lifecycle ls /tmp
poststart  started
pi@raspi001:~/tmp $ k delete -f sample-lifecycle.yaml
# すぐ!
pi@raspi001:~/tmp $ k exec -it sample-lifecycle ls /tmp
poststart  prestop  started

たしかに、postStart, preStopが動いています。
注意しないといけないのが、postStartは、spec.containers[].commandの実行とほぼ同じだそうです。(非同期)

Podの安全な停止とタイミング

terminationGracePeriodSecondsに指定した秒数は、podが削除開始時からの猶予です。
デフォルトで30秒となっています。30秒の間にpreStop+SIGTERMの処理が終わらなければ、
強制的にSIGKILLされて停止されます。ただし、preStopが終わっていなくて30秒たった場合、
SIGTERM処理を2秒だけ実施できます。
terminationGracePeriodSecondsの値は、prePostを必ず終える秒数に設定しましょう。

Nodeをスケジューリング対象から外す

Nodeをkubernetesのスケジューリング対象から外すcordonというコマンドがあります。
Nodeの状態には、SchedulingEnabledとSchedulingDisabledがあり、後者の状態になると、
kubernetesからのスケジューリング対象外となり、たとえばReplicaSetの更新などが機能しなくなります。

cordonコマンドを使うと、指定するNodeがSchedulingDisabledになります。(uncordonは逆)
ただし、現在動作しているPodはスケジューリング対象になったままで、新たに追加するものが
スケジューリング対象外になります。現在動作しているものも対象にしたい場合は、drainコマンド
を使います。
実際に試してみます。

pi@raspi001:~/tmp $ k get nodes
NAME       STATUS   ROLES    AGE   VERSION
raspi001   Ready    master   33d   v1.14.1
raspi002   Ready    worker   33d   v1.14.1
raspi003   Ready    worker   32d   v1.14.1
pi@raspi001:~/tmp $ k cordon raspi002
pi@raspi001:~/tmp $ k get nodes
NAME       STATUS                     ROLES    AGE   VERSION
raspi001   Ready                      master   33d   v1.14.1
raspi002   Ready,SchedulingDisabled   worker   33d   v1.14.1
raspi003   Ready                      worker   32d   v1.14.1
pi@raspi001:~/tmp $ k uncordon raspi002
pi@raspi001:~/tmp $ k get nodes
NAME       STATUS   ROLES    AGE   VERSION
raspi001   Ready    master   33d   v1.14.1
raspi002   Ready    worker   33d   v1.14.1
raspi003   Ready    worker   32d   v1.14.1
pi@raspi001:~/tmp $ k drain raspi002
node/raspi002 cordoned
error: unable to drain node "raspi002", aborting command...

There are pending nodes to be drained:
 raspi002
error: cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): kube-system/kube-flannel-ds-arm-7nnbj, kube-system/kube-proxy-wgjdq, metallb-system/speaker-tsxdk

drainすると、ReplicaSetのように管理したPodであれば、別Nodeに作成されるので良いのですが、
単体Podなど管理されていないものは、削除されてしまいます。上記の警告は、DaemonSetで管理されているPodは、
削除するしかないけど、良いですか?というものです。
そのため、drainをすると、いくつか警告されます。警告内容に従って適宜操作する必要があります。

お片付け

pi@raspi001:~/tmp $ k delete -f sample-healthcheck.yaml -f sample-restart-always.yaml -f sample-restart-onfailure.yaml -f sample-initcontainer.yaml -f sample-lifecycle.yaml

最後に

今回は、ヘルスチェックの動作と、コンテナを停止するまでのステップを学習しました。
わざわざヘルスチェックの処理をアプリケーションに用意せずとも、kubernetesに機能として
存在することに、驚きました。

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

Dockerfileを楽に作りたい [修正版]

はじめに

以前,下記の記事を書きました.
https://qiita.com/RyodoTanaka/items/6f8da0749cbd0afa0ddd

が,うまく行かないことがわかり修正版を作りました.
修正と言っても,もはや作り変えです.

やりたいこと

Dockerfileを楽に作りたいなぁと思った時,どうやりますか?
私は下のような手順で出来るといいなと思ってます.

  1. Docker image の実行
  2. 環境構築
  3. imageからDockerfileを作成

というわけでその手順を記しておきます.

制約

後で仕組みの説明をしますが,下記のような制約があります.

  • Bashじゃないとダメ
  • コマンド総数が2000行を超える場合は,予め.bash_historyの行数制限を解除する必要アリ
  • 環境構築時にエラーが出るようなコマンドを自動認識することは不可能

です.
ここに上げてる以外のこともあるかもしれません...
その場合は是非issue等を立ててください!
一緒に改善していきたいです!

仕組み

前回の記事ではdocker historyを使っていましたが,
これでは image にログインした後のコマンドは全く追えませんでした.
なので,bash_historyを使って環境構築部分を引っ張ってきてやろう!
で,引っ張ってきたやつを無理やりRUNで全部回してやろう!
というのが仕組みです.
ホントそれだけです.

Dockerfileが出来るまでの流れ

1. Docker image の実行

例えば,Ubuntu 16.04をベースにしたいなと思ったとき,まずはimageを引っ張ってきますよね.

$ docker pull <image repository name> 

でもってPullが完了したら,そいつを実行します.

$ docker run -it <image name>

2. 環境構築

実行してるcontainer内で色々環境構築します.
具体的に何をするかは皆様お好きに!
環境構築が終わったらexitコマンドとか使って終了します.
この時,予めコマンド数が増えそうだとわかっているなら,
bash_historyの保存制限を解除してください!!

やり方はこちらが参考になると思います.
https://stackoverflow.com/a/12234989

3. containerからimageを作成する

まずはcontainer 情報を下記コマンドで確認します.
ここからDockerfileを作りたいcontainer IDか名前を取得します.

$ docker ps -a

そしたら,下記コマンドで希望のcontainerを任意の名前のimageにします.

$ docker container commit <container ID> <image name>

一応作成し終わったら,下記コマンドでimageがちゃんと作られてるか確認します.

$ docker images

4. imageからDockerfileを作成

本記事のミソです.
以前の投稿ではワンライナーで出来るとかどうとか言ってましたが,
そもそも仕組みが変わったんでスクリプトを書きました.
dfimageというコマンドを使えるようにしてます.
スクリプトは下記リポジトリに置いてあります.
https://github.com/RyodoTanaka/.bash_extend/blob/master/dfimage.bash
こいつをで読み込んでやれば,

$ dfimage <image name>

とするだけで,Dockerfileを標準出力に出力してくれます.
なのでUNIX系使いの方であれば

$ dfimage <image name> > Dockerfile

とすれば自動でDockerfileが出来上がります!
.bashrcとかで読み込むようにしておくと便利です.

5. 出来上がったDockerfileの手直し

最初の方にも書いたように,余分なコマンド等の認識はしていません.
(ただし,lsコマンドだけは除外するようにしてます)
なので,ご自身でdocker buildとかされながらちゃんと動作するように手直ししてください.

まとめ

というわけで,ようやくそれっぽいものができました.
色々不完全なので,皆様のご指摘をいただけると嬉しいです!!

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

Dockerfileを楽に作りたい(imageから自動生成したい) [修正版]

はじめに

以前,下記の記事を書きました.
https://qiita.com/RyodoTanaka/items/6f8da0749cbd0afa0ddd

が,うまく行かないことがわかり修正版を作りました.
修正と言っても,もはや作り変えです.

やりたいこと

Dockerfileを楽に作りたいなぁと思った時,どうやりますか?
Dockerfileを任意のimageから自動生成できたら嬉しいですよね!
私は下のような手順で出来るといいなと思ってます.

  1. Docker image の実行
  2. 環境構築
  3. imageからDockerfileを作成

というわけでその手順を記しておきます.

制約

後で仕組みの説明をしますが,下記のような制約があります.

  • Bashじゃないとダメ
  • コマンド総数が2000行を超える場合は,予め.bash_historyの行数制限を解除する必要アリ
  • 環境構築時にエラーが出るようなコマンドを自動認識することは不可能

です.
ここに上げてる以外のこともあるかもしれません...
その場合は是非issue等を立ててください!
一緒に改善していきたいです!

仕組み

前回の記事ではdocker historyを使っていましたが,
これでは image にログインした後のコマンドは全く追えませんでした.
なので,bash_historyを使って環境構築部分を引っ張ってきてやろう!
で,引っ張ってきたやつを無理やりRUNで全部回してやろう!
というのが仕組みです.
ホントそれだけです.

Dockerfileが出来るまでの流れ

1. Docker image の実行

例えば,Ubuntu 16.04をベースにしたいなと思ったとき,まずはimageを引っ張ってきますよね.

$ docker pull <image repository name> 

でもってPullが完了したら,そいつを実行します.

$ docker run -it <image name>

2. 環境構築

実行してるcontainer内で色々環境構築します.
具体的に何をするかは皆様お好きに!
環境構築が終わったらexitコマンドとか使って終了します.
この時,予めコマンド数が増えそうだとわかっているなら,
bash_historyの保存制限を解除してください!!

やり方はこちらが参考になると思います.
https://stackoverflow.com/a/12234989

3. containerからimageを作成する

まずはcontainer 情報を下記コマンドで確認します.
ここからDockerfileを作りたいcontainer IDか名前を取得します.

$ docker ps -a

そしたら,下記コマンドで希望のcontainerを任意の名前のimageにします.

$ docker container commit <container ID> <image name>

一応作成し終わったら,下記コマンドでimageがちゃんと作られてるか確認します.

$ docker images

4. imageからDockerfileを作成

本記事のミソです.
以前の投稿ではワンライナーで出来るとかどうとか言ってましたが,
そもそも仕組みが変わったんでスクリプトを書きました.
dfimageというコマンドを使えるようにしてます.
スクリプトは下記リポジトリに置いてあります.
https://github.com/RyodoTanaka/.bash_extend/blob/master/dfimage.bash
こいつをで読み込んでやれば,

$ dfimage <image name>

とするだけで,Dockerfileを標準出力に出力してくれます.
なのでUNIX系使いの方であれば

$ dfimage <image name> > Dockerfile

とすれば自動でDockerfileが出来上がります!
.bashrcとかで読み込むようにしておくと便利です.

5. 出来上がったDockerfileの手直し

最初の方にも書いたように,余分なコマンド等の認識はしていません.
(ただし,lsコマンドだけは除外するようにしてます)
なので,ご自身でdocker buildとかされながらちゃんと動作するように手直ししてください.

まとめ

というわけで,ようやくそれっぽいものができました.
色々不完全なので,皆様のご指摘をいただけると嬉しいです!!

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

Docker で Gentoo コンテナを起動する

普段は macOS を使っていますが, Gentoo を使いたくなるときがちょいちょいあります.
漢なら stage1 からでしょ?とかとか突っ込まれそうですが, Gentoo is 選択 ということでこれはこれで.

1. Dockerfile を作る

Dockerfile
FROM gentoo/portage:latest as portage

FROM gentoo/stage3-amd64:latest

COPY --from=portage /usr/portage /usr/portage

# make.conf
RUN echo "USE=\"\${USE} -X\"" >> /etc/portage/make.conf && \
    echo "GENTOO_MIRRORS=\"rsync://rsync.jp.gentoo.org/gentoo-portage/ \${GENTOO_MIRRORS}\"" >> /etc/portage/make.conf

# timezone
RUN echo 'Asia/Tokyo' > /etc/timezone && emerge --config timezone-data

make.conf に MAKEOPTS, EMERGE_DEFAULT_OPTS, FEATURES を追加してもよいでしょう. USE フラグの取捨選択はお好みで.

2. コンテナを起動する

$ docker build . -t gentoo && docker run --rm -it --name gentoo -d gentoo && docker exec -it gentoo /bin/bash
# ...
f6a4d3c38040 / #

ちな, rm オプションつけてるんで, $ docker stop gentoo をしない限り exit で抜けてもデータは残ってるよ.

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

Dockerで機械学習企画案

解決したい課題

機械学習、深層学習、量子計算機というけど、どこから手をつけたらいいかわからない
DataRobotっていう便利な道具があるらしいが中小企業では手が出ないかもしれない
データの欠損を埋めたり、補完したりできるデータサイエンティストを雇えない

解決策概要

Docker hubにありとあらゆる機械学習、深層学習、量子計算機の動くシステムのソースコード、環境を別々にあげる
それぞれのdockerのシステムに同じデータを投げて、それぞれ計算を競争させる
評価関数の形も複数用意し、評価関数の形による影響を規定値で用意する
データ補完方法を複数用意し、データ補完方法による影響量の幅を提示できる

奉仕詳細

過去に蓄積したデータと、企業または製品の目標値を入れる。
20種類から100種類の計算方式の4類型から20類型ごとの結果を出力する
システムが出力したデータから希望・期待と異なる結果の原因、対策を協議し、必要となるデータを追加入力する。
再度計算して出力する

強みとなる技術

Windows, macOS, Linuxの環境構築
仮装環境の構築
確率・統計計算
機械学習システムの移植・運用
想定外をなくすシステム分析・データ分析

5年中期計画

堅実案

2019 2020 2021 2022 2023
システム設計 10,000,000 20,000,000 20,000,000 20,000,000 20,000,000
協力企業 12 24 36 48 60
収入 12000000 24000000 36000000 48000000
損益 -10,000,000 -8,000,000 4,000,000 16,000,000 28,000,000 30,000,000

拡大+補填案

2019 2020 2021 2022 2023
システム設計 10,000,000 20,000,000 30,000,000 40,000,000 50,000,000
協力企業 12 24 48 72 96
収入 12000000 24000000 48000000 72000000
投資 6000000 6000000 6000000 18000000
損益 -4,000,000 -2,000,000 0 8,000,000 22,000,000 24,000,000

現実案

2019 2020 2021 2022 2023
システム設計 5,000,000 10,000,000 20,000,000 20,000,000 20,000,000
協力企業 6 12 24 48 96
収入 6000000 12000000 24000000 48000000
投資 6000000 6000000 6000000 18000000
損益 1,000,000 2,000,000 -2,000,000 4,000,000 28,000,000 33,000,000

班構成

企画担当(専任)
営業(兼任)
クリエータ1(兼任)
クリエータ2(兼任)
エンジニア(兼任)

文書履歴(document history)

ver. 0.01 初稿 20190530 午後
ver. 0.02 収支計画、班構成追記 20190530 夜

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

Travis CIからSlackに通知する際の認証情報の暗号化(travis encrypt)について

TL;DR

  1. .travis.ymlに直トークン書きたくないからtravis encryptしたい
  2. Travis「Travis CLI 使ってね」っ gem install travis
  3. このプロジェクトrubyじゃないし、ローカルにもruby入ってない…

というときに、rubyのDockerイメージを使ってアプリケーションに影響なくサクッとやりたい

準備

実践したのはmac + Docker for Mac環境ですが、Docker使えれば大丈夫なはずです

  • macOS 10.14.5
  • docker 18.09.2

想定プロジェクト

  • GitHubで管理されている
  • travis-ci.comでCIを回している
  • アプリケーションルートに.travis.ymlがある

手順

$ cd /path/to/project
$ docker run -it --rm --volume $(pwd)/:/app ruby bash
# cd app
# gem install travis
# travis login --com --github-token XXXXXXXX
# travis encrypt "xxxxxx:XXXXXXXX" --add notifications.slack --com
# exit

--comオプションについて

travis-ci.comを使ってるので--comオプションつけましたが、travis-ci.orgな場合はオプション無しでよいのかもしれません(未検証)

--github-tokenオプションについて

GitHubで二段階認証を有効化している場合は、Personal access tokenを発行して指定する必要があります
GitHub > Settings > Developer settings > Personal access tokens から発行できます
必要なスコープはrepo, user:emailだと思われます
有効化していない場合は--github-tokenオプションなしでやれば、普通にuser/passの認証がされるのでそれで大丈夫だと思われます(未検証)

travis encryptコマンドの部分はSlackのTravisアプリ画面の「セットアップの手順」に書いてあるのでコピーしちゃえば大丈夫です

上記うまくいけば.travis.ymlに暗号化された認証情報が追記されているはずなので、コミットしちゃえばOK

+notifications:
+  slack:
+    secure: XXXXXXXXXXXXXXXX...

まとめ

Circle CIは設定ファイルじゃなくWeb上の設定画面でWebhookのURL指定するだけで通知できたので楽ちんだった

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

Jupyterのmatplotlibを使用する際の日本語豆腐を解決

TL;NR

dockerでmatplotlibの文字化けと戦う

環境:

docker on ubuntu18.04
python3

課題:

image.png

アクション:

matplotlibのfont.familyのフォントを指定

import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'IPAGothic'
plot somthing

UserWarning: findfont: Font family ['IPAGothic'] not found. Falling back to DejaVu Sans(prop.get_family(), self.defaultFamily[fontext]))

fontキャッシュ削除

rm ~/.cache/matplotlib/fontList.*

fontダウンロード(今回はIPAGothicを使用)
https://ipafont.ipa.go.jp/old/ipafont/download.html
image.png

matplotlibのfontPathを特定

print(matplotlib.matplotlib_fname())
/usr/local/lib/python3.5/dist-packages/matplotlib/mpl-data/matplotlibrc

ファイルを展開し.ttfファイルをdockerのfontPathにcopy

docker cp ipag.ttf コンテナNAME:/usr/local/lib/python3.5/dist-packages/matplotlib/mpl-data/fonts/ttf/

Done

image.png

恒久対応

matplotlibrc設定ファイルを修正

cp /usr/local/lib/python3.5/dist-packages/matplotlib/mpl-data/matplotlibrc ~/.config/matplotlib/

ファイル内のFontセッションを修正

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