20190330のAWSに関する記事は8件です。

SageMaker を ローカルPC に構築する

あまり見かけないのですが、SageMakerのライブラリは GitHub に公開されているので、ローカルに構築可能です。

SageMaker は無料枠が無いので、お金をかけたくない個人ユーザーは活用すると良いと思います。

リポジトリ

SageMaker Python SDK

The SageMaker Python SDK is built to PyPI and can be installed with pip as follows:

pip install sagemaker

You can install from source by cloning this repository >and running a pip install command in the root directory of the repository:

git clone https://github.com/aws/sagemaker-python-sdk.git
cd sagemaker-python-sdk
pip install .

Amazon SageMaker Examples - SageMakerのサンプルソース集

使い方

Anaconda をインストールして、Jupyter Notebook や Jupyter lab と一緒に使いましょう。

ただ、conda skeleton でビルドしようとして上手くいかなかったので、公式の手順の通りに pip コマンドで入れてしまいました。。。

併せて、awscli もインストールすると使い方が広がります。

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

CloudFormationの基本のキ

AWSのサービス"CloudFormation"をについての勉強メモ

AWS CloudFormationとは

  • AWSが提供するInfrastructure as Codeを実現するためのサービス
  • AWSリソースの設定やプロビジョニングを担ってくれる

Infrastructure as Codeとは

  • 一言で言うと、ITインフラの構築や維持作業をコード化すること

メリット

  • 自動化
    • インフラ構築をコード化し、それを実行することで素早く・正確にインフラを構築する
  • 冪等性
    • 人の手を介さないため、一度コードを作ってしまえば、ミスなく同じ環境を同じように構築可能
    • 「冪等性」と言う言葉は数学界で用いられる言葉で、1回の操作でもn回の操作でも結果が変わらないこと
  • 変更管理
    • 再利用性の高いコードとして管理することで、インフラ設定をバージョン管理でき、変更後の差分が分かりやすくなる

デメリット

  • 学習コスト
    • ツールを利用するのに、まずそのツールを理解しなければならない
  • 部分変更に時間がかかる
    • サーバーの設定を少しいじるだけでも、コードを修正して適用になるため、手作業よりも時間がかかる

CloudFormation実行の主な流れ

  1. テンプレートを作成する
    • テンプレートの拡張子はyamlとjsonがある
    • 特別な理由がない場合は可読性が高いので、yamlを用いるのが良いと言われている
  2. スタックを作成する
    • スタックはCloudFormationで構築するインフラのひとかたまり
    • =テンプレートごとの単位

基本のテンプレート

スクリーンショット 2019-03-30 22.06.18.png

  • 9つのセクションを記述できる
  • ここではよく使うセクションについて詳しく書きます

AWSTemplateFormatVersion(形式バージョン)

  • バージョン指定することでテンプレートの機能を識別する
  • 現在、2010-09-09のみなので、自動的に指定する
  • スクリーンショット 2019-03-30 18.54.58.png

Description

  • CloudFormationの説明
  • AWSコンソールではスタック一覧の説明タブに表示される
  • スクリーンショット 2019-03-30 18.57.02.png
  • スクリーンショット 2019-03-30 22.37.27.png

Parameters

  • テンプレート実行時に任意の値を設定したい場合に記述する
  • スクリーンショット 2019-03-30 19.03.51.png
  • スクリーンショット 2019-03-30 22.39.04.png

Resources

  • 構築するAWSリソースを記述する
  • スクリーンショット 2019-03-30 22.35.12.png
  • スクリーンショット 2019-03-30 22.43.45.png

Outputs

  • リソースを出力する値を記述する
  • 例えば、インスタンスのPublicIPなど出力したりする
  • スクリーンショット 2019-03-30 22.11.19.png
  • スクリーンショット 2019-03-30 22.46.45.png
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Elastic BeanstalkにSpring Bootアプリケーションをデプロイ

Spring Bootを使ったJavaアプリケーションをElastic Beanstalk(AWSのPaaS)上にデプロイする手順をざっくりおさらいします。
初投稿なので、至らないところもあるかとは思いますが、ご了承ください。

BeanstalkへのデプロイはAWSのコンソールからでもできるのですが、今回はCIツールからも実行したいので、CLI(EB CLI)を使います。

前提

今回はBeanstalkの設定手順を説明します。
SpringBootアプリの作成については割愛します。
ビルドツールはgradleです。

環境

Mac OSX10.14.3

EB CLIのインストール

homebrewでBeanstalkのCLIをインストールします。

$ brew install awsebcli

AWS CLIのインストール

Access KeyとSecret Access Keyの設定を保存するためにAWSのCLIもインストールします。

$ brew install awscli

アクセスキー設定

$ aws configure
AWS Access Key ID [None]: {アクセスキーを入力}
AWS Secret Access Key [None]: {シークレットアクセスキーを入力}

プロジェクト設定

デプロイはプロジェクトのディレクトリで行います。

$ cd workspace/ebdemo/demo

初めにプロジェクトの設定です。

$ eb init

対話型で設定していきます。

リージョン
Select a default region
1) us-east-1 : US East (N. Virginia)
2) us-west-1 : US West (N. California)
3) us-west-2 : US West (Oregon)
4) eu-west-1 : EU (Ireland)
5) eu-central-1 : EU (Frankfurt)
6) ap-south-1 : Asia Pacific (Mumbai)
7) ap-southeast-1 : Asia Pacific (Singapore)
8) ap-southeast-2 : Asia Pacific (Sydney)
9) ap-northeast-1 : Asia Pacific (Tokyo)
10) ap-northeast-2 : Asia Pacific (Seoul)
11) sa-east-1 : South America (Sao Paulo)
12) cn-north-1 : China (Beijing)
13) cn-northwest-1 : China (Ningxia)
14) us-east-2 : US East (Ohio)
15) ca-central-1 : Canada (Central)
16) eu-west-2 : EU (London)
17) eu-west-3 : EU (Paris)
18) eu-north-1 : EU (Stockholm)
(default is 3): 9
アプリケーション
Select an application to use
1) [ Create new Application ]
(default is 1):

Enter Application Name
(default is "demo"):
Application demo has been created.
プラットフォーム→SpringBootの場合はJava
Select a platform.
1) Node.js
2) PHP
3) Python
4) Ruby
5) Tomcat
6) IIS
7) Docker
8) Multi-container Docker
9) GlassFish
10) Go
11) Java
12) Packer
(default is 1): 11

Select a platform version.
1) Java 8
2) Java 7
(default is 1):
SSH
Cannot setup CodeCommit because there is no Source Control setup, continuing with initialization
Do you want to set up SSH for your instances?
(Y/n): Y

Select a keypair.
1) key
2) [ Create new KeyPair ]
(default is 2): 2

デプロイ

デプロイの前にアプリケーションのjarをプロジェクトルートにコピーします。

$ cp build/libs/demo-0.0.1-SNAPSHOT.jar .

デプロイします。

$ eb create
Enter Environment Name
(default is demo-dev):
Enter DNS CNAME prefix
(default is demo-dev):

Select a load balancer type
1) classic
2) application
3) network
(default is 2):

数分かかります。

動作確認

動いてます。

$ curl http://demo-dev.ap-northeast-1.elasticbeanstalk.com
Hello, World!

2回目以降のデプロイ

2回目以降は以下のコマンドだけでデプロイできます。
SSH、アクセスキー等設定しておけば、CIツールから自動デプロイ可能です。

$ gradle clean build test
$ cp build/libs/demo-0.0.1-SNAPSHOT.jar .
$ eb deploy
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS KMSのマスターキーとデータキー

AWSで暗号化の話しになると登場するKMSについて勉強したのでこのエントリーを書きました。
公式のKMSドキュメントはKMS全般の優れたドキュメントですが、ここではマスターキーとデータキーの関係に絞って書こうと思います。

マスターキーとデータキー

KMSの言うところのマスターキー(CMKとかカスタマーマスターキーとも呼ばれます)と、データキーって何?どんな関係なの?という点を図解します。例えばS3のサーバーサイド暗号化を例にとると、KMSを使う場合は以下のような関係になります。

S3_SSE_with_KMS.jpg

KMSがやってくれるのは、マスターキーの管理とデータキーの復号ということですね。データの暗号化に使うデータキーは使う側でちゃんと管理しないといけないと。

マスターキー

マスターキーの作成ですが、AWSマネージドの方法に加えて、ユーザー側で生成した暗号鍵をマスターキーとしてKMSに保管することもできるみたいです。

KMS_MasterKey_AWS.jpg
KMS_MasterKey_external.jpg

自分で生成した秘密鍵をKMSに登録する具体的方法は公式ドキュメントに記載があります。RSAで暗号化してやりとりするんですねー。

データキー

データキーの生成は、KMSにGenarateDataKeyリクエストをすることで行います。
KMS_DataKey.jpg
平文データキーが不要な場合は、GenerateDataKeyWithoutPlaintextリクエストと言うのもあります。

マスターキーの権限管理

カスタマーマスターキーを使用する権限をIAMユーザーやIAMロールに付与しようとした場合、IAMのポリシーをどうのこうのしただけでは不十分で、KMSのキーポリシーでも権限を与えてあげる必要があります。KMSのキーポリシーはCMK毎に設定するCMKに対する権限のポリシーです。
具体的にどうすればいいのかは公式ドキュメントにあります。

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

AWS S3を使ってホームページを公開する

背景

独自ドメインを取得してホームページを開設したかった。
レンタルサーバを利用しなくてもAWSのS3を利用して簡単にできるようだったので、試しにやってみる。
参考(AWSチュートリアル)

全体像

Untitled Diagram.jpg

作業概要

だいたいの作業手順はこんな感じです。

  1. 独自ドメインの購入
  2. バケット作成
  3. Route53へバケットのエイリアスレコード追加

作業内容

独自ドメインの購入

AWSドキュメントに、より詳細な内容が書かれていますので参考に。AWSドキュメント

  • AWSコンソールにログイン後、サービスからRoute53を選択する。
  • 画面真ん中あたりのテキストボックス(Type a domain name)に取得したいドメイン名を入力し、Checkボタンをクリックする。(.com以外のドメインが欲しい場合は右隣のリストボックスから選択すること)
    image.png

  • Add to cartをクリックし、欲しいドメインをカートに加える。
    (画像はgetsampleapp.comをカートに加えた後のキャプチャです)
    画面を下にスクロールしてcontinueボタンをクリックする。
    image.png

  • ドメインの詳細情報を入力します。
    image.png

  • 購入します。
    以下の作業を行うと、Complete Purchase

    • 真ん中あたりあるチェックボックス「I have read and agree...」 にチェックを入れる
    • 登録したメールアドレスにAWSから確認用メールが届くので、メール内のリンクにアクセスする。 image.png

作成が完了するとroute53のRegistered domainsに出現します。
image.png

バケットの作成

AWSサービスの中からS3を選択し、バケットを作成する。
ホスティングするウェブサイトと同じ名前のバケットを作成すること(AWSチュートリアル参考)。

バケットポリシーを設定する

画面下のポリシージェネレータを利用すると簡単にjsonを生成することができます。
image.png
こんな感じで良いかと思います(ARNは作成したS3バケットのARNを設定してください)
image.png
Generate Policyボタンをクリックし、画面に表示されたポリシーをコピペして貼り付けてください。
※バケットのパブリックアクセス設定内の新規のパブリックバケットポリシーをブロックする (推奨)にチェックが入っているとポリシーの保存ができないので要注意です(そりゃそうか...って感じですが)。
image.png

ウェブサイトのホストとして設定する

AWSチュートリアルを参考に、S3のバケットをウェブサイトのホストとして利用する設定をします。

ひとまず簡単なindex.htmlを作成してホスティングの設定をするのが良いかと思います。

S3エンドポイントへアクセスしてみる

設定がうまくいっていればエンドポイントへアクセスできるはずなのでお試ししてみてください。
AccessDenyエラーが出るときはバケットのアクセス権限周りの設定を再確認してみると良いかもしれません。

Route53へエイリアスレコードの追加

AWSチュートリアルのエイリアスレコードを追加するを参考に、エイリアスレコードを設定します。
Nameと同じ名前でないとAlias Targetとして表示されないので注意です。同じ名前のバケット名を作成したのはそのためか。と一人で納得しました。
image.png

作成後、http://xxxx.com(xxxxは購入したドメイン名)にアクセスすると、いい感じにアクセスできます。

詰まったところ

全体的にあまりつまるところはなかったけど、地味にちょこちょこ引っかかってしまいました...

バケットポリシーが保存できない

S3アクセス権限の「パブリックアクセス設定」 新規のパブリックバケットポリシーをブロックするにチェックが入ってた。チェックを外して保存できた

S3のエンドポイントにアクセスしてもコンテンツが表示されない

S3アクセス権限の「パブリックアクセス設定」 バケットにパブリックポリシーがある場合、パブリックアクセスとクロスアカウントアクセスをブロックする にチェックが入ってた。チェックを外してアクセスできた

エイリアスターゲットにS3のバケットが表示されない

バケット名のスペルが誤っていた。正しい名前(Route53レコード追加画面のNameと同じ名前)のバケット名を作成したらエイリアスターゲットとして選択することができた

今後の課題と感想

ACMとCloudFrontを利用してHTTPS化したい。文書を書くのに途中で力尽きてしまって急に適当になってしまいがちなので、なんとか工夫したい...段々雑になってごめんなさい...

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

AWSのElastic Beanstalkにtd-agent3をデプロイする

目次
1. はじめに
2. .ebextension内にtd-agent3の設定ファイルを作る
3. .ebextension内にtd-agent3のインストールファイルを作る
4. デプロイ

1. はじめに

環境
fluentd-v1.0(td-agent3)
Amazon Linux 1

2. .ebextensionでtd-agent3の設定ファイルを作る

Elastic Beanstalk以下(eb)では、.ebextensionという設定ファイルを追加することによって環境設定が可能です。

  • 作成したファイルの拡張子は.configとし、YAMLもしくはJSON形式にします。
  • 設定ファイルはアルファベット順に実行されます。

(設定ファイル読み込み例)
以下のように設定ファイルを作成した場合
.ebextensions/01td-agent3.configが先に読み込まれます。

.ebextensions/01td-agent3.config
.ebextensions/02td-agent-install.config


(設定例 01-td-agent.config)

設定の中身はバージョンによって書き方が異なるので注意が必要ですので、使用されるtd-agentのバージョン確認することをおすすめします。

例えばbufferプラグインでも書き方が全く異なります。

td-agent2.config
buffer_type file
td-agent3.config
<buffer>
 @type file
</buffer>

(Amazon Linuxのバージョン確認方法)
使用したいebに接続した状態で$ cat /etc/system-releaseと入力すると、
=> Amazon Linux AMI release 2017.09のように使用してるバージョン確認ができます。

下記は01td-agent.configの設定例です。
※設定内容は適当ですので、実際に設定したい内容に書き換えてください。

設定例01-td-agent.config
files:
 "/etc/td-agent/td-agent.conf":
    owner: root
    group: root
    content: |

  <match pattern1>
    <buffer>
      @type file
      path /var/log/fluent/s3
    </buffer>
  </match>

  <match pattern>
    @type s3

    aws_key_id YOUR_AWS_KEY_ID
    aws_sec_key YOUR_AWS_SECRET_KEY
    s3_bucket YOUR_S3_BUCKET_NAME
    s3_region YOUR_S3_BUCKET_REGION
    path logs/

    <buffer tag,time>
      @type file
      path /var/log/fluent/s3
      timekey 3600
      timekey_wait 1m
      timekey_use_utc true
      chunk_limit_size 256m
    </buffer>
  </match>

3. .ebextensionでtd-agent3のインストールファイルを作る

# errors get logged to /var/log/cfn-init.log. See Also /var/log/eb-tools.log
commands:
  01-command:
    command: echo 'Defaults:root    !requiretty' >> /etc/sudoers

  02-command:
    command: curl -L https://toolbelt.treasuredata.com/sh/install-amazon1-td-agent3.sh | sh

  03-command:
    command: /etc/init.d/td-agent restart

インストールするURLはご自身の環境に合わせてください。↑はAmazon Linux 1の場合です。

4. デプロイ

eb環境がない方はeb initでEB上でアプリケーションを作成し、
eb createで環境を構築してください。この辺の説明は省きます。

すでにある方はeb deployで設定内容反映させてください。
設定がおかしかったりすると、deployに失敗すると思うので原因はログで確認してください。

eb sshで接続したあと起動確認しましょう。

便利コマンド
バージョン確認
$ rpm -q td-agent
$ td-agent --version

起動、停止、再起動、ステータス
$ sudo /etc/init.d/td-agent start
$ sudo /etc/init.d/td-agent stop
$ sudo /etc/init.d/td-agent restart
$ sudo /etc/init.d/td-agent status

コマンドライン上でS3プラグインがどんな設定項目を持っているか確認
td-agent --show-plugin-config output:s3

参考
Installing Fluentd Using rpm Package
設定ファイル (.ebextensions) による高度な環境のカスタマイズ
AWS Elastic Beanstalk の詳細な環境設定 » 設定オプション

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

TCPのLISTEN見て、ヘルスチェック応答させる

背景

AWSのALB(Application Load Balancer)を使いたかったんですけど、アプリがヘルスチェックにうまく反応しない。。
(ALBは正常のHTTPステータスコードとして、200 ~ 499の範囲で指定可能ですが、アプリが500を正常で応答する仕様 orz)

そしてアプリ側の改修して頂ける雰囲気はないので、ヘルスチェックを書きました。

サマリ

最終的に出来たコード

・ net/httpでヘルスチェック用webを起動
・ health check requestを受けたら、net.Listen でサービスが稼働しているポート20000番のポートをListenを試みる
・ Listen出来た場合(サービス停止) → 404を応答
  or 
・ Listen出来なかった場合(サービス稼働) → 200を応答

handler作成

ヘルスチェックのリクエスト受けた時に、特定ポート(今回は20000port)の Listen を試みる handler です。
listen出来たら、404 NotFoundで、Listen出来なかったら、200OKを応答する。

var (
    svcProtocol = "tcp4"
    svcPort     = ":20000"
    okMsg       = "healthy"
    ngMsg       = "unhealthy..."
)

func checker(writer http.ResponseWriter, request *http.Request) {
    // Try to listen on svcProtocol and svcPort.
    listenchecker, err := net.Listen(svcProtocol, svcPort)

    if err == nil {
    // able to listen it... Which means, the service has stopped...ng
        writer.WriteHeader(http.StatusNotFound)
        fmt.Fprint(writer, ngMsg)
        defer listenchecker.Close()
        return
    }
    // not able to listen it. Which means, the service is working...ok!!!
    fmt.Fprint(writer, okMsg)
    return
}

handler登録してヘルスチェック応答web起動

ヘルスチェックのパスとポートを決めて、 handler を登録して web を起動

health.go
var (
    healthPath  = "/health"
    healthPort  = ":80"
)
func main() {
    http.HandleFunc(healthPath, checker)
    http.ListenAndServe(healthPort, nil)
}

windows 用にコンパイル

-ldflags="-H windowsgui" はプロンプト起動させない様にするとか。

GOOS=windows GOARCH=386 go build -ldflags="-H windowsgui" health.go

AWS側

リスナー設定

まずはサービスで利用するポートを指定する。
image.png

ヘルスチェック設定

次にヘルスチェックの指定
ポイントはヘルスチェックのポートを トラフィックポート ではなく、 上書き を指定しヘルスチェック専用ポートを指定すること。

image.png

実験開始

まずは、windowsサーバでコンパイルした自作ヘルスチェックを起動

c:\>health.exe

ヘルスチェック(80)と、サービス(20000)共に起動(LISTEN)している

c:\>netstat -aon | find "80"
  TCP         0.0.0.0:80             0.0.0.0:0              LISTENING       3552
c:\>netstat -aon | find "20000"
  TCP         0.0.0.0:20000          0.0.0.0:0              LISTENING       3636

curlでヘルスチェック先を叩くと200が返ってくる。

~ ❯❯❯ curl -i http://ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com/health
HTTP/1.1 200 OK
Date: Sat, 30 Mar 2019 03:33:21 GMT
Content-Length: 7
Content-Type: text/plain; charset=utf-8

healthy

サービスを停止し、再度curlで確認するとちゃんと連動してるのが確認できた。

~ ❯❯❯ curl -i http://ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com/health
HTTP/1.1 404 Not Found
Date: Sat, 30 Mar 2019 03:34:17 GMT
Content-Length: 12
Content-Type: text/plain; charset=utf-8

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

Windows7環境なのにdocker入れて開発することになった話【③docker開発環境編】

はじめに

2章では、不足していたライブラリやソフトウェアを導入し、実際に動作確認を行いました。3章では、2章で動作確認を行ったモジュール群を、docker環境下でどのように実行させるのかを記述していきます。ついにdockerについて触れます。章の構成としては、以下の構成となります。

  • 開発環境における動作確認

    1. コンテナにマウントするためのpythonファイルをテストする
      • python XXXX.pyにてモジュールを実行する(2章で解説したため割愛)
    2. DockerFile、docker-compose.yml、shellを駆使して「1.」と同様の動きを実現する
  • デプロイ環境における動作確認

    1. 開発環境にて作成したDockerFile、docker-compose.ymlを利用してデプロイする

本章を読んでいただくことで、以下のDockerFileを作ることのメリットが伝わると幸いです。

メリット1

dockerをインストール済みの環境(1章参照)であれば、DockerFileとソースコードを共有することで、環境構築なしで実行することができる。GitHubではソースコードの共有まではできるが、開発環境の共有はできないため、共同開発を行う際は非常に有用なメリット。

メリット2

コンテナを利用可能なサービス(AWSではESC)において、簡単にデプロイできる。(本章では開発環境までしか触れられないので次章以降になります)

メリット3

そのアプリケーションを実行するための環境が、DockerFile内に全て書かれているため、開発環境・本番環境に対してどのようなソフトウェアやライブラリが必要か一目で分かる。

一応デメリットも

  • DockerはLinuxカーネルを利用しているため、Linux環境下を推奨。(Windows10からはDocker ToolboxからWSLを利用することで実行できるが、まだまだ不安定なのが現状
  • 開発者が、開発環境にインストールされるソフトウェア/ライブラリを意識せずに開発を行えてしまうため、開発終盤までいっても環境を把握している人はチームに数人しかいないことになる

ついにdockerに触れられるということで前置きが長くなりましたが、今しばらくの間お付き合いください。

第3章

技術バリバリの人「動作確認お疲れ!DockerFile書けた?」

わたし「書けるわけないじゃないですか。そもそもなんですかdockerって」

技術バリバリの人「1章で教えて上げたじゃん」

技術バリバリの人「あ、あと開発環境はもちろんgit使うし、ビルドの情報とかは全部Dockerファイルに書くね。さらに言えばdocker-compose使っちゃえば複数のサーバーをビルドする情報がチーム全体でで同時に管理できちゃったりするねー」

わたし「そういえば単語は一回聞きましたね。でも何言ってるか分からないです。簡単に教えてください!」

技術ばりばりの人「…分かった、Dockerの中身の話を全部話すと長くなるから、1章の辞書整理を見てね。今からは、実際にdockerを使った際に実感できるメリットについて2つ話すね」

docker

技術ばりばりの人「まずこの図を見てね。これは、今回のアプリケーションのライブラリやソフトウェアを、dockerを利用して管理した場合の概念図だよ。左の青い部分がDockerfileで、今回は2つのDockerfileを作ろう。上の『GetNews_Dockerfile』の部分が、インターネットからデータを取得するモジュールに必要なライブラリ/ソフトウェア郡だね。下の『Post_Dockerfile』部分はまだ実装していないけど、取得したデータを外部に送信する部分だね」

わたし「『GetNews_Dockerfile』に、2章でインストールした、スクレイピングで使用する『beautifulsoup4』、AWSにローカルからアクセスする『boto3』、自然言語処理で利用する『mecab』が書いてますね」

技術ばりばりの人「そうだね。2章で既に君が開発環境にインストールしたライブラリ/ソフトウェアを書いただけだよ。次は真ん中の黄色い部分、docker-compose.ymlについて説明するね」

技術ばりばりの人「docker-composeを使うことで、Dockerfileに定義されたコンテナを共通管理することができるんだ。開発したソフトウェアをコンテナ上のどの領域にマウントして、最初に実行するコマンドは何を実行するか等を定義することができるよ」

わたし「もしdocker-composeが無かったらどうなるんですか?」

技術ばりばりの人「もしdocker-composeを使わなかった場合、ビルド・デプロイ・破棄・スケール・ネットワーク設定などのコマンドを、それぞれのDockerコンテナ/イメージに対して実行する必要があるんだ」

わたし「ビルド・デプロイ・破棄だけでも単純にコンテナの数だけコマンドたたく回数が増えちゃうんですね」

技術ばりばりの人「そうだね。正確にはスケールやネットワーク設定についてはDockerfileでやれちゃう部分もあるんだけど、ソフトウェア/ライブラリ部分はDockerfile、ネットワークやスケールなどのインフラ周りについてはdocker-composeに任せちゃう運用が分かりやすいね」

わたし「開発環境の管理が楽なことがなんとなく分かってきました!」

技術ばりばりの人「じゃぁこれでもDockerfileとdocker-compose.ymlが書けるね!よろしく!」

わたし「はい!」

技術ばりばりの人「あ、そうだ、MeCabのDocker化は1癖も2癖もあるらしいから気をつけてね。まぁ大丈夫だね!それじゃ!」

わたし「え、ちょ」

辞書整理

本文章(第3章)を読む上で頭に入れておいたほうが良い文言をピックアップ。文中分からない文言が出たら見返してください。(不足あれば、コメントいただけたら追記していきます)

忙しい人はここだけ読めばDockerの概念がつかめるので、下記は補足として読んでください。

  • コンテナ

    • ホストOS(Linux限定)のkernel機能を利用することで、仮想サーバのような立ち振る舞いをする
    • プロセス・メモリ・デバイス・ネットワーク等、仮想サーバとして必要な部分についてはコンテナごとに保有する
    • ホストOSから見ると、単に1プロセスが起動しているように見えている
    • kernel部分は複数コンテナで共有しているため、kernelにかかわるような操作はできない(正確にはできるがやらない)
    • kernelを共有しているため、kernel依存のエラーである「オープンしているファイルの最大数を超える」等のエラーが、ゲストOS(コンテナ)・ホストOSをまたいで生じることがある
    • Dockerとコンテナは意味が異なり、「Dockerソフトウェアを用いてコンテナという概念を扱っている」が正しい
    • Dockerにおいては、コンテナがkernelを共有して実行している部分は「Docker daemon」が担っている
    • 参考:コンテナ技術の基礎知識
  • Dockerデーモン

    • Linux kernelをコンテナから実行する、いわばホストOSとゲストOS(コンテナ)の橋渡しの部分
    • ホストOSの環境変数、プロキシ設定、DNS設定などをコンテナでも利用したい場合は、Dockerデーモンのオプションを修正する
    • コンテナから見ると、ある意味kernelのような存在
    • Linuxのコマンド、「systemctl」で操作できる
    • 参考:Dockerデーモンに関するもう少し詳しい説明
  • Dockerイメージ

    • コンテナを実行する時に必要なファイルシステム
    • イメージ・レイヤ(Dockerイメージを構成するファイルシステム)の集まり
    • 難しいので、OSおよび必要なアプリケーションに必要なソフトウェア一式が書き込まれているディスクのようなものだと認識していれば良い
    • 自分で1から作成することも可能であるが、GitHubのような形でイDockerメージを管理しているDockerHubから取得することも可能
    • Dockerイメージを作成することをビルド、Dockerイメージをビルドし、アプリケーションをその環境下で実行させることをデプロイと呼んでいる
    • 参考:Dockerイメージとは?【Docker解説】
  • WSL

    • Windows Sybsystem for Linux
    • Windows環境からLinuxの実行環境を実現するサブシステムのこと
    • Windows10以降しか使えない
    • Windows10以降にDockerがWindows環境でも使えるようになった原因
    • Windows10環境にてDockerを利用するには、DockerToolboxをインストールすることで、同ツールがWSLを利用して、Linuxカーネルを叩いている仕組み
    • とはいえ実際動作確認を行っていく中で、まだ不安定であるという噂や、アップデートで動くようになっているという噂もある
    • 参考:WSL上でDocker Engineが動くようになっていたっぽいという話

1.Dockerの設定

第1章で書いた内容も重複しますが、インストールした後の設定が一番難しく、しくじるともちろん動かないので、再掲します。ちなみに、公式ドキュメントが一番参考になります。参考:Docker-docs-ja

前提条件

第1章のDockerのインストールが完了している

proxyおよびDNS設定

社内等プロキシ環境下で実行している場合、Dockerデーモン実行時にプロキシの設定を渡す必要があるため、Dockerデーモンのオプション設定を変更する。(Ubuntu環境を想定しています。)

  • プロキシおよびDNSサーバの設定
    • $ sudo mkdir -p /etc/systemd/system/docker.service.d/
    • $ sudoedit /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://各プロキシサーバ:8080/" "HTTPS_PROXY=http://各プロキシサーバ:8080/" "NO_PROXY=127.0.0.1,localhost" "DOCKER_NETWORK_OPTIONS=--dns 各DNSサーバ"
ExecStart=
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS

Dockerデーモンのオプションファイル自体は別にありますが、『docker.service.d/』以下に記載した設定が、Dockerデーモン実行時に上書かれて実行されます。「ExecStart=」の部分はおまじない。最初に空実行を設定することで、2回目の実行時にオプションを指定した状態で上書き実行ができる仕組み。

  • Dockerデーモンのリロード
    • sudo systemctl daemon-reload
  • Dockerの再起動
    • sudo systemctl restart docker

2.Dockerfileの記載

2章で開発したモジュール郡を動かすためには、下記を「Getnews_Dockerfile(拡張子不要)」という名称で作成する。

Get_news_Dockerfile

FROM python:3.6.5

RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y sudo
RUN pip install --upgrade pip

# ----------- install scrayping module at Python ---------------
RUN pip install beautifulsoup4==4.6.3

# --------------------- mecab configure ------------------------
RUN apt-get install mecab mecab-ipadic libmecab-dev -y
RUN pip install mecab-python3==0.7
RUN git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git /usr/src/mecab-ipadic-neologd \
  && /usr/src/mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -y -p /var/lib/mecab/dic/mecab-ipadic-neologd \
  && rm -rf /usr/src/mecab-ipadic-neologd

# -------------- install aws module at Python ------------------
RUN pip install boto3==1.7.4

WORKDIR ./

解説

  • FROM python:3.6.5
    • DockerHub上から、どのDockerイメージをベースにカスタマイズするかを指定。今回の場合は、Python3.6.5を導入したDockerイメージをベースにカスタマイズを加えている
  • RUN apt-get update && apt-get upgrade -y ~ RUN pip install --upgrade pip
    • apt-getやpipなどソフトウェア管理ツールを最新化しておくおまじない
  • # ----------- install scrayping module at Python ---------------以降
    • スクレイピングに利用するライブラリのインストール
  • # --------------------- mecab configure ------------------------以降
    • MeCabを利用する際に必要なライブラリ/ソフトウェア郡のインストール
  • # -------------- install aws module at Python ------------------以降
    • PythonからAWSアクセスに必要なライブラリのインストール
  • WORKDIR ./
    • デプロイ時、コンテナ内の最初に居るディレクトリを指定

3.docker-compose.ymlの記載

「2.Dockerfile」の記載にて定義したイメージを、コンテナ化して実行するための「docker-compose.yml」を記載する。

docker-compose.yml

version: '2'

services:
    get-news:
      env_file: .env
      build:
        context: ./
        dockerfile: Get_news_Dockerfile
      volumes:
        - ./shell:/root/shell
        - ${get_news_root_dir}/backEndLogic:/root/backEndLogic
        - ${host_aws_credential}:/root/.aws
      command: >
        bash -c "chmod +x /root/shell/get_news.sh && /root/shell/get_news.sh"
      tty: true

解説

  • version: '2'
    • docker-composeのバージョンを指定する。HTMLの一番初めに書くバージョン宣言と同じ(HTML5からは書かないが…)
  • get-news:
    • 任意のコンテナ名称。コンテナを立ち上げる際、ターミナルから指定する名称となる
  • env_file .env
    • AWSのシークレットキーやマウントのパスなど、ホストOSの環境依存でパスを指定する部分については別途「.env」ファイルを作っている。Dockerの設定を完璧に行っても、唯一各環境で書き換える必要がある部分。docker-compose.ymlと同フォルダに作成している
  • build:
    • どのDockerfileをbuildするかをここに書く
    • contextにDockerfileのあるフォルダを指定。今回の場合はdocker-compose.ymlと同フォルダに作成している
    • dockerfileに、このコンテナ(今回の場合get-news)をbuildするために利用するDockerfile物理名称を指定
  • volumes:
    • 各種ローカルからコンテナへのマウント情報。今回の場合は、①shell(後述)、②作成したモジュール郡、③AWSクレデンシャルをマウントする
    • ①shellについては各開発者環境で共通して利用するため、docker-compose.ymlと同フォルダに作成し、envを介さずに相対パスを記載
    • ②作成したモジュール郡および③AWSクレデンシャルについては各開発者環境で異なるため、envで指定した環境変数を記載
  • command: >
    • デプロイ後最初に実行するコマンドを記載。今回はshell(後述)を呼び出すことで、2章で作成したPythonモジュールの管理や、MeCabの辞書コンパイルなどを行う

参考(.envファイル中身)

# ------------------以下ホストの環境に合わせて変更してください ------------------

# ソースディレクトリへのPath. 各コンテナは以下Pathを参照して環境を構築します.
# 指定したディレクトリは、コンテナ上からmountされ参照されます.
get_news_root_dir=/home/username/backEndLogic

# AWSのcredential情報を記載したファイルパス
host_aws_credential=/home/username/.aws

インフラ周りの設定情報についても、docker-compose.ymlに書く。たとえばファイルオープン数が最大に達してしまい、コンテナにもっとリソースを割きたい場合は、volumeと同じ階層に以下のように追記すると良い。

      ulimits:
        nproc: 65535
        nofile:
          soft: 20000
          hard: 40000

※この場合、後述するshellの中にスタックサイズの開放コマンド$ ulimit -s unlimitedを書く必要がある。

4.shellの記載

1~3までで、コンテナ環境の構築や、コンテナ環境へのPythonモジュールのマウントは完了した。しかし、デプロイ後に実際にPythonモジュールを実行したり、MeCabの設定が必要だったりするので、shellを外だしで作成する。

get_news.sh

  • MeCabの辞書がローカルで更新されていた場合、Dockerコンテナ上で毎回ユーザ辞書を更新する必要があるため、shellに任せました
  • 作成したPythonモジュールを実行するために、main.pyに飛ばしました(ここは各々好きに作ればよいと思います)
get_news.sh
# ユーザ辞書のコンパイル
cd /root/backEndLogic/mecabDict

/usr/lib/mecab/mecab-dict-index \
  -d /var/lib/mecab/dic/mecab-ipadic-neologd \
  -u /root/backEndLogic/mecabDict/select_dic.dic \
  -f utf-8 \
  -t utf-8 select_dic.csv

# mecabの設定ファイルにユーザ辞書を追記
cd /etc
sed -i -e 's@.*userdic.*@userdic = /root/backEndLogic/mecabDict/select_dic.dic@' mecabrc

# モジュールのおいてあるパスへ移動
cd /root/backEndLogic/

# News収集機能を実行
python /root/backEndLogic/main.py

main.py

main.py
import subprocess

def main():

    subprocess.check_call(['python','ニュース取得機能.py'])
    print("complete get_news")

    subprocess.check_call(['python','ニュース選定機能.py'])
    print("complete select_target")

if __name__ == '__main__':
    main()

※実際のアプリケーションとは異なるため、簡易的に「ニュース取得機能.py」、「ニュース選定機能.py」を呼び出すような記載としています

docker-compose実行

ここまでくれば、後は2つコマンドを実行してあげるだけです。その前に、現状のフォルダ構成はこうなっています。

.../
    - shell
        - get_news.sh
    - Get_news_Dockerfile
    - docker-compose.yml
    - .env

docker-compose.ymlと同フォルダに、Dockerfileや.env、shellが置いてあります。(docker-compose.ymlの記載次第)

いよいよコマンドを実行します。実行するコマンドはたったの2つ。(コンテナが増えても同様に2つです)

build

プロキシ環境下
- $ docker-compose build --build-arg https_proxy=${https_proxy} --build-arg http_proxy=${http_proxy} get-news
非プロキシ環境下
- $ docker-compose build get-news

コンテナ起動&デプロイ

  • $ docker-compose up

あとがき

わたし「Docker環境で、pythonモジュールが動きました!」

技術バリバリの人「これで実際にAWS環境にデプロイするときも簡単にできるし、モジュールが複雑化しても実行環境を修正するのが簡単になったね!」

技術バリバリの人「次回はついに、取得したデータをフロントエンドに出力する部分を作っていこう!」

続く

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