- 投稿日:2020-12-18T23:42:12+09:00
Docker+Rails+AWS(EC2+RDS)を使ってデプロイした
概要
AWSを使ってアプリケーションを公開している人は多く、私も実際に体験してみたくタイトル通りDockerで環境構築し、Railsでアプリケーションを開発し、AWSで実際にデプロイすることにチャレンジしました。
AWSは無料枠内にてデプロイまで目指します。前提
- アプリケーションはGithubを使って管理する。
- 各サービスのアカウント登録は済ませている。(AWS、Github等)
- AWSはIAMユーザーを作成し、必要なセキュリティ、ポリシーを割り当てている。
- アプリケーションはDockerを使用して環境構築している。
AWSの設定
AWSのサービスの設定は極力IAMユーザーにて行います。まず、AWSにIAMユーザーでログインする。
- VPCの作成
まずはVPCの作成を行います。VPCサービスのページを開き、メニューからVPCを選択。VPCの作成を選択します。
VPC名、CIDRブロックを設定し、VPCを作成します。
- サブネットの作成
サブネットの作成を行います。
サブネットはEC2用のサブネットを1つ、RDS用のサブネットを2つ用意します。
メニューからサブネットを選択し、サブネットの作成を選択します。
先ほど作成したVPCを選択し、サブネット名、アベイラビリティゾーン、CIDRブロックを設定し、サブネットを作成を選択します。
※RDS用のサブネットはアベイラビリティゾーンを別々にします。
- インターネットゲートウェイの作成
インターネットに接続するためにインターネットゲートウェイを設定します。
メニューからインタネットゲートウェイを選択し、インターネットゲートウェイの作成を選択します。
名前を設定し、インターネットゲートウェイの作成を選択します。
アクションからVPCにアタッチを選択し、作成したVPCにアタッチします。
- EC2インスタンスの作成
EC2ダッシュボードに開き、インスタンスを起動を選択し、EC2インスタンスを作成します。
EC2インスタンスは無料枠で使えるマシンイメージとインスタンスタイプを選択します。
セキュリティグループは新しく作成します。
SSH接続を行いたいのでSSHの設定を行います。
タイプ プロトコル ポート範囲 ソース HTTP TCP 80 0.0.0.0/0 SSH TCP 22 マイIP 設定に問題がなければ起動を選択します。
インスタンスを作成するときにキーペアを作成します。
キーペアはEC2にSSH接続する際必要となります。新しいキーペアの作成を選択し、キーペア名を設定しローカルにダウンロードしておきます。インスタンスメニューの[ステータスチェック]が終了し、[インスタンスの状態]が[実行中]になれば、無事インスタンスが起動したこととなります。
続いてElastic IPを設定します。
メニューよりElastic IPを選択します。Elastic IP アドレスの割り当てを選択し、新しいアドレスの割り当てを選択し、割り当てを選択します。
作成したElastic IPを選択し、アクションからElastic IPアドレスの関連付けを選択します。
作成したEC2インスタンスを設定してElastic IPアドレスをEC2に関連付けます。
- RDSの作成
RDSを作成する前に、RDS用のサブネットグループの作成を行います。
RDSメニューよりサブネットグループを選択し、DBサブネットグループの作成を選択します。サブネットグループ名、VPCを選択し、RDS用に作成したサブネット2つを設定し、作成をします。
RDSサービスを開き、データベースの作成を選択します。
データベースはMySQLを選択します。基本的には既存の設定で大丈夫ですが、無料利用枠という箇所は忘れずに選択します。バージョン等は自身の使用するバージョンを設定します。データベース名、マスターユーザー名、マスターパスワードは適宜設定します。
後に、Railsの設定に必要となります。(作成後、確認することができます)
作成したVPC、サブネットグループを選択します。セキュリティグループは新規作成を選択し、新しいセキュリティグループを作成します。
データベースの作成を選択し、データベースを作成します。データベース用のセキュリティグループのインバウンドルールを変更します。
タイプ プロトコル ポート範囲 ソース MYSQL/Aurora TCP 3306 EC2のセキュリティグループのID Railsの設定
- RDSの設定
RDSの情報をcredentials.yml.encに書き込みます。
docker-compose run -e EDITOR="vim" app rails credentials:edit
credentials.yml.encrds: host: RDSのエンドポイント database: RDSのデータベース名 username: RDSのマスターユーザの名前 password: RDSのマスターパスワードconfig/database.ymlのproductionの箇所にRDSの情報を挿入します。
database.yml#省略 production: <<: *default host: <%= Rails.application.credentials.rds[:host] %> database: <%= Rails.application.credentials.rds[:database] %> username: <%= Rails.application.credentials.rds[:username] %> password: <%= Rails.application.credentials.rds[:password] %>
- Docker-compose.ymlの編集
データベースはRDSを使用するためdb:の箇所は全てコメントアウトします。volumes:のmysql-data:もコメントアウトします。
アプリケーションを本番環境で立ち上げるため、app:のcommand:に-e productionを追加します。docker-compose.ymlversion: '3' services: # db: # image: mysql:5.7 # command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci # env_file: # - ./.env # volumes: # - mysql-data:/var/lib/mysql # ports: # - "4306:3306" app: build: . env_file: - ./.env command: bundle exec puma -C config/puma.rb -e production init: true volumes: - .:/myproject - public-data:/myproject/public - tmp-data:/myproject/tmp - log-data:/myproject/log # depends_on: # - db web: build: context: containers/nginx init: true volumes: - public-data:/myproject/public - tmp-data:/myproject/tmp ports: - 80:80 # depends_on: # - app volumes: # mysql-data: public-data: tmp-data: log-data:
- nginx.comfの編集
server_nameのxx.xx.xx.xxの箇所にElastic IPアドレスを入力します。
nginx.confupstream myproject { server unix:///myproject/tmp/sockets/puma.sock; } server { listen 80; server_name xx.xx.xx.xx [or localhost]; #省略 } }
- その他の設定
その他Github等外部に知られたくないKEYや環境変数などは.envファイルを作成し、そちらに書き込みます。dotenv-railsを使うとGitを使用する際管理をし易くなります。
gemfilegem 'dotenv-rails'$ bundle install.gitignoreファイルに.envファイルを記述することで、githubにpushされなくなります。
.gitignore/.envconfig/environmentsのproduction.rbを編集します。
下記内容を編集すると、本番環境で立ち上げ時に便利です。production.rbconfig.assets.js_compressor = Uglifier.new(harmony: true) config.assets.compile = true以上、完了したらアプリケーションをgithubへpushします。
AWSでアプリケーションをデプロイ
- EC2のSSH接続する。
EC2にSSH接続するための設定を行います。
$ mkdir ~/.ssh $ mv ~/Downloads/myapp.pem ~/.ssh/ $ chmod 600 ~/.ssh/myapp.pem $ ssh -i ~/.ssh/myapp.pem ec2-user@xxx.xxx.xxx.xxxmyapp.pemはダウンロードしたキーペアの名前です。chmodで権限を変更後、キーペアを使用してEC2にログインします。ec2-userはAWS linuxのデフォルトユーザーです。xxx.xxx.xxx.xxxはEC2インスタンスのElastic IPを入力します。
まず初めにyumをアップデートします。
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo yum update -y
- EC2にDocker環境を作る
EC2にDockerとdocker-composeをインストールします。
# Dockerをインストール [ec2-user@xxx.xxx.xxx.xxx ~]$ sudo yum install -y docker [ec2-user@xxx.xxx.xxx.xxx ~]$ sudo service docker start [ec2-user@xxx.xxx.xxx.xxx ~]$ sudo usermod -G docker ec2-user [ec2-user@xxx.xxx.xxx.xxx ~]$ exit $ ssh -i ~/.ssh/myapp.pem ec2-user@xxx.xxx.xxx.xxx [ec2-user@xxx.xxx.xxx.xxx ~]$ sudo chkconfig docker on # docker-composeをインストール [ec2-user@xxx.xxx.xxx.xxx ~]$ sudo curl -L "https://github.com/docker/compose/releases/download/インストールするバージョン/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose [ec2-user@xxx.xxx.xxx.xxx ~]$ sudo chmod +x /usr/local/bin/docker-compose
- gitをインストール
Githubからアプリケーションをクローンするためにgitをインストールします。
[ec2-user@xxx.xxx.xxx.xxx ~]$ sudo yum install -y git [ec2-user@xxx.xxx.xxx.xxx ~]$ git clone [Githubのパス]
- ローカルから必要ファイルをコピー
credentialsの解読するためのmaster.keyと.envファイルをローカルからコピーします。
[ec2-user@xxx.xxx.xxx.xxx ~]$ exit $ scp -i ~/.ssh/myapp.pem master.key ec2-user@xx.xxx.xxx.xx:myapp/config/ $ scp -i ~/.ssh/myapp.pem .env ec2-user@xx.xxx.xxx.xx:myapp/
- コンテナの起動
$ ssh -i ~/.ssh/myapp.pem ec2-user@xxx.xxx.xxx.xxx [ec2-user@xxx.xxx.xxx.xxx ~]$ cd myapp [ec2-user@xxx.xxx.xxx.xxx ~/myapp]$ docker-compose build [ec2-user@xxx.xxx.xxx.xxx ~/myapp]$ docker-compose up -d [ec2-user@xxx.xxx.xxx.xxx ~/myapp]$ docker-compose exec app bin/rails db:create db:migrate RAILS_ENV=productionElastic IPアドレスにアクセスして正しく表示されれば完了です。
まとめ
AWSを使ってデプロイをすることは、初学者にはかなりハードルが高い内容だと思っておりましたが、素晴らしい文献等が豊富にあったため乗り越えることができました。
所々修正したり、試行錯誤しながらデプロイまで行ったので、全く同じやり方でできるかはわかりませんが、現場私ができる最適な方法だと考えております。気になった点
参考記事によっては「この方法では開発環境で動いてしまうのでは?」「本番環境でないためRDSが使用されていないのではないか?」と思う部分もあり、いくつかの記事を参考にさせて頂きました。database.ymlのproduction:をRDSに指定したのであれば、本番環境でアプリケーションを立ち上げなければRDSは機能しないと考えております。(勘違いであれば申し訳ありません)
docker-composeの設定次第でなんとかできるのかもしれませんが、もう少しリサーチをしてみようと思いました。課題
せっかくDockerを使用したのでAWSのECSやFargateを駆使してデプロイすることを考えるべきだったと思いました。
次の機会があれば挑戦したいと思います。その他
私はS3も取り入れました。そちらは別記事にてまとめております。
AWS_S3+Ruby on Rails_Active Storageで画像データを保存参考記事
無料!かつ最短?で Ruby on Rails on Docker on AWS のアプリを公開するぞ。
EC2上でRailsアプリケーションにDockerを導入する(Rails、Nginx、RDS)
見ながらやろう! AWSを始めよう -VPC構築編-
Rails5.2から追加された credentials.yml.enc のキホン
- 投稿日:2020-12-18T23:18:03+09:00
Amazon ECRにプライベートリポジトリを作成してイメージのpush/pullを実行する
1. はじめに
AWS re:Invent 2020で発表されましたが、Amazon ECRでパブリックレジストリが利用できるようになりました。
しかし、今回はそれとは関係なく、プライベートレジストリを使用します。
これまでECRを触ってこなかったので、使ってみたという内容です。
2. 構成
2台のLinuxサーバを使用します。1台目からイメージをpushし、2台目はイメージをpullします。
ECRはリージョンサービスで、VPCエンドポイントも利用できます。(今回は使用しません)
3. ECRの設定
リポジトリの作成
ECRのリポジトリを以下の設定で作成します。
可視性設定:プライベート
リポジトリ名:test-app-repo
タグのイミュータビリティ:無効
プッシュ時にスキャン:有効
KMS暗号化:有効
4. EC2(1台目)からのpush
まず、ECRレジストリに対してDockerを認証します。「Login Succeeded」と表示されたことを確認します。
WARNINGが出ていますが、そのまま進めます。これについては本記事の「8. 警告&エラー集」で説明します。$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com WARNING! Your password will be stored unencrypted in /home/ec2-user/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded今回は「test-app」というイメージをpushしたいと思います。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE test-app v1.0 72b199328340 10 days ago 461MBdocker tagコマンドでpushする対象にタグを設定します。
指定する形式は、「AWSアカウントID.dkr.ecr.リージョン.amazonaws.com/リポジトリ名:タグ」です。
タグを省略した場合は、自動でlatestのタグが付きます。$ docker tag test-app:v1.0 \ > 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/test-app-repo:v1.0タグ付けした結果を確認します。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/test-app-repo v1.0 72b199328340 10 days ago 461MB test-app v1.0 72b199328340 10 days ago 461MBでは、イメージをpushします。
$ docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/test-app-repo:v1.0コンソールから確認すると、イメージタグにv1.0が追加されたことが確認できます。
5. EC2(2台目)からのpull
5-1. IAMポリシーの作成とアタッチ
2台目のEC2はaws configureで認証情報(アクセスキー、シークレットアクセスキー)を渡していないので、
そのままではECRにアクセスできません。
以下のIAMポリシーを作成してEC2のIAMロールにアタッチし、ECRにアクセスできるようにします。
IAMポリシー名:AmazonECRFullAccessjson{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:*" ], "Resource": "*" } ] }5-2. EC2からのpull
まずは、1台目と同じようにECRレジストリに対してDockerを認証します。
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.comイメージをpullします。
$ docker pull 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/test-app-repo:v1.0結果を確認します。2台目のLinuxサーバがECRからイメージをpullすることができました。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/test-app-repo v1.0 72b199328340 10 days ago 461MB6. v2.0をpushする
次に、タグ「v2.0」を付けたイメージもpushしてみたいと思います。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/test-app-repo v1.0 72b199328340 10 days ago 461MB 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/test-app-repo v2.0 72b199328340 10 days ago 461MBイメージをpushします。
$ docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/test-app-repo:v2.07. イメージタグを削除する
v2.0が不要になったと仮定して、イメージタグを削除したいと思います。
(aws configureでregionを指定してある場合は、コマンドでは指定不要です)$ aws ecr batch-delete-image --repository-name test-app-repo --image-ids imageTag=v2.0 --region ap-northeast-1 { "failures": [], "imageIds": [ { "imageTag": "v2.0", "imageDigest": "sha256:58d3c26bee377e039c0ce5c2ef92ed2ce10b956bf3dc0cf5dba4b4d6f56aaf94" } ] }再度コンソールから確認すると、v2.0が削除されています。
イメージを削除する場合は、イメージのダイジェストを指定すれば削除できます。
参考:https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/delete_image.html8. 警告&エラー集
警告①
$ aws ecr get-login --region ap-northeast-1 --no-include-email $ docker login -u AWS -p {認証トークン} https://123456789012.dkr.ecr.ap-northeast-1.amazonaws.com WARNING! Using --password via the CLI is insecure. Use --password-stdin.→AWS CLI バージョン 1.17.10 より前のバージョンを使用している場合はget-loginコマンドで認証しますが、
セキュリティリスクがあり非推奨です。AWS CLIのバージョンを上げて、get-login-passwordを使用することが推奨されます。
参考:https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/Registries.html警告②
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com WARNING! Your password will be stored unencrypted in /home/ec2-user/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store→Dockerのデフォルトの動作として、ログインパスワードを暗号化せずにconfig.jsonに保存します。
外部のクレデンシャルストアに保存する方がより安全という警告です。
参考:https://docs.docker.com/engine/reference/commandline/login/#credentials-storeエラー①
$ docker pull 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/test-app-repo:v1.0 Error response from daemon: Get https://123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/v2/test-app-repo/manifests/v1.0: no basic auth credentials→ECRレジストリに対してDockerを認証していないと出るエラーです。
エラー②
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com An error occurred (AccessDeniedException) when calling the GetAuthorizationToken operation: User: arn:aws:sts::123456789012:assumed-role/IAMロール名/インスタンスID is not authorized to perform: ecr:GetAuthorizationToken on resource: * Error: Cannot perform an interactive login from a non TTY device→aws configureで認証情報を指定していない、あるいはEC2のIAMロールにECRへのアクセスに必要な
IAMポリシー(本記事ではAmazonECRFullAccess)がアタッチされていない場合に出るエラーです。
- 投稿日:2020-12-18T22:24:58+09:00
ECRからdocker pullしてコンテナを起動して中身を確認する
Amazon ECRにDockerイメージを保存していて、それをAWS CodePipelineでFargateにデプロイするという構成において、デプロイに失敗した。コンテナがなにかおかしいらしいのでコンテナを確認したい。という状況になり、ECRからDockerイメージを落としてきて確認したくなったが、いつもやりかたを忘れるので備忘録として残しておく。
ECRからdocker pullする
$ docker pull your-aws-account-id.dkr.ecr.ap-northeast-1.amazonaws.com/xxx/yyy/zzz:latest上記コマンドを実行すると認証エラーになった。(イメージのURLはAWSコンソールでECRを選択して選ぶ)
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/Registries.html#registry_auth
ここを確認するとレジストリ認証が必要らしい。$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin your-aws-account-id.dkr.ecr.ap-northeast-1.amazonaws.comこれでログインする。
aws cli v1ではget-login-passwordがなかったので注意。
事前に環境変数にAWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYとAWS_SESSION_TOKENをセットする必要があるかも。これが成功したら先程のdocker pullを再実行すると成功する。
docker pullしたイメージを起動する
$ docker imagesまずは上記コマンドでイメージが追加されてることを確認する。
$ docker run -it your-aws-account-id.dkr.ecr.ap-northeast-1.amazonaws.com/xxx/yyy/zzz:latest /bin/bash最後に
/bin/bash
と入れることでコンテナ内にbashで入れる。あとはご自由に。
- 投稿日:2020-12-18T22:14:00+09:00
sql-migrateを使ってみる
はじめに
この記事はITRC Advent Calendar 2020の18目の記事です。
前の記事?→ 【Neovim】琴葉葵が教えるおすすめのテキストエディタ【Voiceroid】
こんにちはRIN1208です。今回はsql-migrateを使ってみたら便利だったのでそのお話をしようかと思います。必要環境
- docker-compose
- mac os
上記の環境で説明していきます
sql-migrateとは?
- SQLite, PostgreSQL, MySQL, Oracleなどの色々なデータベースをサポートしている
- CLIツールまたはライブラリとして使用可能
- go getで取得可能
- Go用のマイグレーションツール
構築する
リポジトリはこちら
今回sql-migrateを使用する上で必要なファイルは以下の4つです
- dbconfig.yml
- docker-compose.yml (docker-composeを使用して今回お話しするので)
- Dockerfile (go getでインストールするためgoの環境にしています)
- sqlのマイグレーションファイル
docker-compose.ymlを書く
docker-compose.ymlを書いていきます。今回は確認用にphpmyadminを使用しています
version: '3.7' services: api: build: . ports: - "8080:8080" tty: true volumes: - ./:/app working_dir: /app environment: - MYSQL_USER=root - MYSQL_PASSWORD=root - MYSQL_HOST=[mysql] - MYSQL_PORT=3306 - MYSQL_DATABASE=test mysql: image: mysql:5.6 restart: always environment: - MYSQL_ROOT_PASSWORD=root - MYSQL_DATABASE=test command: > --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --innodb_file_per_table --innodb_file_format=BARRACUDA --innodb_large_prefix=1 phpmyadmin: image: phpmyadmin/phpmyadmin ports: - 8000:80 environment: - PMA_HOST=mysql - PMA_PASSWORD=root - PMA_USER=root - PMA_ARBITRARY=1 links: - mysql depends_on: - mysqlDockerfileを書く
次にdockerfileを書いていきます
FROM golang:1.14 RUN go get github.com/rubenv/sql-migrate/...sqlのマイグレーションファイルを書く
次にsqlのマイグレーションファイルを書きます。ここではsqlをそのまま書く為主キーや外部キーを簡単に設定できます。ファイル名は.sqlのファイルであればなんでも大丈夫です。
-- +migrate Up CREATE TABLE IF NOT EXISTS user ( user_id VARCHAR(128) NOT NULL PRIMARY KEY, user_name VARCHAR(128) ); -- +migrate Down DROP TABLE IF EXISTS user;dbconfig.ymlを書く
次にdbconfig.ymlを書きます。ここではsql-migrateのconfigを書きます。
development: dialect: mysql datasource: ${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(${MYSQL_HOST}:${MYSQL_PORT})/${MYSQL_DATABASE}?parseTime=true dir: .
- dialect
この部分では使用するDBを選択しています。今回はmysqlを使用するのでmysqlと書いてあります。
- datasource
この部分ではmysqlに接続するための情報を記入しています。今回はそのまま書くのではなく環境変数から取得しています。環境変数はdocker-compose.ymlにて定義してあります。- dir
この部分では実行するsqlファイルの場所を選択しています。/api/db下に置いてある場合はapi/dbと記入してください。実行してみる
それでは以下のコマンドを実行してマイグレートをしてみましょう。
docker-compose exec api bash -c "sql-migrate up"http://localhost:8000/ に接続しphpmyadminで確認無事userテーブルが作成できて入れば成功です。
終わりに
ここまで読んでくださりありがとうございます。
sql-migrateが便利だったので今回記事に書きました。
sql-migrateを使おうとしている方の手助けになれば幸いです。
また間違っている点などがございましたらコメントなどで指摘していただけると助かります。
- 投稿日:2020-12-18T21:47:06+09:00
io_uringを使うプログラムはCentOS 8上のDockerで動かない
Linux kernel 5.1から導入されたio_uringという非同期IOのカーネル機能がありますが、それを使うDockerイメージはCentOS 8で動きませんよと。
知ってる人にはまあ、そうだよねという事ではあるのですが。Docker/Linuxコンテナのポータビリティは万能ではないんですよと議論したい場合の論拠として。
io_uring使うプログラムをUbuntu 20.10で作る
1.OSがUbuntu 20.10の仮想マシンを作る。
https://ubuntu.com/download2.Dockerをインストールする。
https://docs.docker.com/engine/install/ubuntu/3.Docker上でUbuntu 20.10イメージを起動する。
# docker run -it --rm --name=io_uring-test ubuntu:20.10 bash
4.一応、uname -aで利用中のカーネルを確認。
(c)# uname -a
(実行結果) root@17003dd74a2f:/liburing/examples# uname -a Linux 17003dd74a2f 5.8.0-33-generic #36-Ubuntu SMP Wed Dec 9 09:14:40 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux5.gccとio_uringのライブラリ、gitをインストールする。
(c)# apt-get update
(c)# apt-get install -y build-essential liburing-dev git
6.io_uringのサンプルプログラムを入手する。
https://blogs.oracle.com/linux/an-introduction-to-the-io_uring-asynchronous-io-framework
(c)# git clone https://github.com/axboe/liburing.git
7.サンプルプログラムをコンパイルする。
(c)# cd liburing/examples
(c)# gcc -Wall -O2 -D_GNU_SOURCE -o io_uring-test io_uring-test.c -luring
8.プログラムを実行する。当然、こちらは動作する。
(c)# ./io_uring-test io_uring-test.c
(実行結果) root@08ad6f4c804c:/liburing/examples# ./io_uring-test io_uring-test.c Submitted=1, completed=1, bytes=22569.コンテナからデタッチ(C-p, C-q)し、コミット、イメージ保存する。
# docker commit io_uring-test io_uring-test
# docker save io_uring-test -o io_uring-test.tar
CentOS 8のDockerでそのプログラムを動かす
1.OSがCentOS 8.3の仮想マシンを作る。
https://www.centos.org/download/2.Dockerをインストールする。
https://docs.docker.com/engine/install/centos/3.先のDockerイメージ(io_uring-test.tar)をCentOS 8マシンにコピーし、ロードする。
# docker load -i io_uring-test.tar
4.コンテナを起動する。
# docker run -it --rm io_uring-test bash
5.一応、uname -aで利用中のカーネルを確認。ホストのCentOS 8と同じ4.18なはず。
(c)# uname -a
(実行結果) root@824c737193b6:/# uname -a Linux 824c737193b6 4.18.0-240.1.1.el8_3.x86_64 #1 SMP Thu Nov 19 17:20:08 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux (ついでに) root@824c737193b6:/liburing/examples# cat /etc/os-release NAME="Ubuntu" VERSION="20.10 (Groovy Gorilla)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.10" VERSION_ID="20.10" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=groovy UBUNTU_CODENAME=groovy5.サンプルプログラムを動かす。
(c)# cd liburing/examples/
(c)# ./io_uring-test io_uring-test.c
(実行結果) root@824c737193b6:/liburing/examples# ./io_uring-test io_uring-test.c queue_init: Function not implementedまあ、動きませんよね、と。
- 投稿日:2020-12-18T21:47:06+09:00
io_uringを使うプログラムはCentOS 8上のDockerでは動かない
Linux kernel 5.1から導入されたio_uringという非同期IOのカーネル機能がありますが、それを使うDockerイメージはCentOS 8で動きませんよと。
知ってる人にはまあ、そうだよねという事ではあるのですが。Docker/Linuxコンテナのポータビリティは万能ではないんですよと議論したい場合の論拠として。
io_uring使うプログラムをUbuntu 20.10で作る
1.OSがUbuntu 20.10の仮想マシンを作る。
https://ubuntu.com/download2.Dockerをインストールする。
https://docs.docker.com/engine/install/ubuntu/3.Docker上でUbuntu 20.10イメージを起動する。
# docker run -it --rm --name=io_uring-test ubuntu:20.10 bash
4.一応、uname -aで利用中のカーネルを確認。
(c)# uname -a
(実行結果) root@17003dd74a2f:/liburing/examples# uname -a Linux 17003dd74a2f 5.8.0-33-generic #36-Ubuntu SMP Wed Dec 9 09:14:40 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux5.gccとio_uringのライブラリ、gitをインストールする。
(c)# apt-get update
(c)# apt-get install -y build-essential liburing-dev git
6.io_uringのサンプルプログラムを入手する。
https://blogs.oracle.com/linux/an-introduction-to-the-io_uring-asynchronous-io-framework
(c)# git clone https://github.com/axboe/liburing.git
7.サンプルプログラムをコンパイルする。
(c)# cd liburing/examples
(c)# gcc -Wall -O2 -D_GNU_SOURCE -o io_uring-test io_uring-test.c -luring
8.プログラムを実行する。当然、こちらは動作する。
(c)# ./io_uring-test io_uring-test.c
(実行結果) root@08ad6f4c804c:/liburing/examples# ./io_uring-test io_uring-test.c Submitted=1, completed=1, bytes=22569.コンテナからデタッチ(C-p, C-q)し、コミット、イメージ保存する。
# docker commit io_uring-test io_uring-test
# docker save io_uring-test -o io_uring-test.tar
CentOS 8のDockerでそのプログラムを動かす
1.OSがCentOS 8.3の仮想マシンを作る。
https://www.centos.org/download/2.Dockerをインストールする。
https://docs.docker.com/engine/install/centos/3.先のDockerイメージ(io_uring-test.tar)をCentOS 8マシンにコピーし、ロードする。
# docker load -i io_uring-test.tar
4.コンテナを起動する。
# docker run -it --rm io_uring-test bash
5.一応、uname -aで利用中のカーネルを確認。ホストのCentOS 8と同じ4.18なはず。
(c)# uname -a
(実行結果) root@824c737193b6:/# uname -a Linux 824c737193b6 4.18.0-240.1.1.el8_3.x86_64 #1 SMP Thu Nov 19 17:20:08 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux (ついでに) root@824c737193b6:/liburing/examples# cat /etc/os-release NAME="Ubuntu" VERSION="20.10 (Groovy Gorilla)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.10" VERSION_ID="20.10" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=groovy UBUNTU_CODENAME=groovy5.サンプルプログラムを動かす。
(c)# cd liburing/examples/
(c)# ./io_uring-test io_uring-test.c
(実行結果) root@824c737193b6:/liburing/examples# ./io_uring-test io_uring-test.c queue_init: Function not implementedまあ、動きませんよね、と。
- 投稿日:2020-12-18T21:28:51+09:00
Docker+Prometheusで外形(URL)監視を作る
初のAdvent calendarは最近触ってみたPrometheusという監視ツールの構築について書きます
みなさん、Webサイトの死活監視はされていますでしょうか?
「自分で構築できるの?」「SaaSと契約するほど大きなシステムじゃないんだけど・・・」「サーバを1から立てるのは辛い」などなど、私もハードルが高い機能の1つだと思っていました
が、DockerとPrometheusを組み合わせることで意外と簡単に外形監視の仕組みを作ることができるので、書いていこうと思います外形(URL)監視とは何か?
外形監視とは、WebサイトやAPIサーバが正常に動いているか?をHTTPアクセスで確認する監視方法です
「レスポンスが正常か?」「規定の秒数以内にレスポンスが返却されるか?」などを確認します
良いところとしては、ユーザと同じ方法でアクセスするため、ネットワークを含めてシステムまたはAPI全体の正常/異常を確認することが可能です
サーバのリソース(CPUやメモリなど)を内部から監視する方法と組み合わせて使うことが多いと思います
AWSのサービスを使っていますが、簡単に説明した図になります背景
- Webシステムに対して外形監視をしたい
- SaaSもあるがシステムが大規模じゃない場合はオーバースペックだと感じた(大規模ならお金かけて使った方が良いのかもしれないけれど)
- 柔軟な選択ができるよう環境(開発端末・クラウドなど)に関係なく構築できるようにしたい
今回やること
- 監視ツールであるPrometheusを使って外形監視をする
- OSに寄らずに環境構築できるDocker+Prometheusで構築する
- 開発端末で起動する
- 異常を検知した場合、Slackに通知する
説明しないこと
ここでは書かないので、調べてみてください...
- ターミナルの操作方法
- Docker, docker-composeについて
環境
今回はMacでやりますが、Dockerを使っているので、windowsでもlinuxでも起動できます
- Mac : 10.15.5
- Docker : 19.03.8
- docker-compose : 1.25.5
使用したDockerイメージ
- prom/prometheus : 2.19.1
- prom/blackbox-exporter : 0.17.0
- prom/alertmanager : 0.21.0
フォルダ・ファイル構成
━ docker-compose.yml ┣ prometheus ┃ ┗ alert_roles.yml ┃ ┗ prometheus.yml ┣ blackbox_exporter ┃ ┗ config.yml ┗ alertmanager ┗ config.ymldocker-compose.ymlの作成
- prometheus:本体のイメージ
- blackbox_exporter:URL監視してくれるexporter(外部ライブラリ的なもの)
- alertmanager:アラートが発生した時にメッセージ通知をしてくれるexporter(今回はslack通知で使用する)
- 各々のポート番号とconfigファイルを設定していきます
docker-compose.ymlversion: '3' services: prometheus: image: prom/prometheus container_name: prometheus volumes: - ./prometheus:/etc/prometheus command: "--config.file=/etc/prometheus/prometheus.yaml" ports: - 9090:9090 restart: always blackbox_exporter: image: prom/blackbox-exporter:latest volumes: - ./blackbox_exporter/config.yml:/etc/blackbox_exporter/config.yml alertmanager: image: prom/alertmanager container_name: alertmanager volumes: - ./alertmanager:/etc/alertmanager command: "--config.file=/etc/alertmanager/config.yaml" ports: - 9093:9093 restart: alwaysblackbox_exporter
URL監視の設定をyml形式で記載していきます
modules:
には確認したいプロトコルごとに設定を作っていきます(tcp、pop3、sshもデフォルトで用意されています)
今回はPOSTメソッドの設定としてhttp_post_2xx:
を追加しています
headers:
にはHTTPヘッダを設定することができます
設定できる内容についてはblackbox_exporterのConfigurationを参照してくださいblackbox_exporter/config.ymlmodules: http_2xx: prober: http http: http_post_2xx: prober: http http: method: POST headers: xxx: yyyyprometheus
prometheus本体で外形監視の設定を記載します
評価内容は``alert_roles.yml''に定義していますprometheus/prometheus.ymlglobal: # prometheusがexporter等に情報を取りに行く間隔(今回はblackbox_exporter) scrape_interval: 15s # ruleの評価を行う間隔(今回はrule_filesで指定されているalert_roles.ymlが評価内容) evaluation_interval: 15s external_labels: monitor: 'codelab-monitor' rule_files: - /etc/prometheus/alert_roles.yml alerting: alertmanagers: - scheme: http static_configs: - targets: - alertmanager:9093 scrape_configs: - job_name: 'prometheus' static_configs: - targets: - prometheus:9090 # 1つの監視条件をjobという単位で扱う - job_name: 'blackbox_http' metrics_path: /probe # blackbox_exporterのconfig.ymlで定義しているmoduleを指定 params: module: [http_post_2xx] static_configs: # 監視対象のURLを指定 - targets: - '[target_url]' relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox_exporter:9115alert_roles.yml# alertの定義 groups: - name: blackbox_exporter rules: - alert: http_success # 評価するメトリクスと条件 # probe_successの条件を"blackbox_http"のjobに適用しています expr: probe_success{job='blackbox_http'} != 1 # 評価NGとするまでの継続時間(10秒間alert状態の場合NG) for: 10s labels: severity: critical annotations: summary: "{{ $labels.instance }}: http request not return 200" description: "{{ $labels.instance }} http request not return 200 for more than 10 seconds."alertmanager
alertmaneagerは通知を行います
今回はslackへの通知を設定しています
slackのwebhookは公式を参照くださいconfig.tmlglobal: # slackのwebhookURLを指定 slack_api_url: '[slack webhook url]' smtp_smarthost: 'localhost:25' smtp_require_tls: false smtp_from: 'Alertmanager' route: receiver: 'test-route' # グループ化の設定(アラート名) group_by: '[alertname]' # alertグループの通知の送信を最初に待機する時間 group_wait: 10s # alertグループでの最小送信間隔(新しいアラート送信まで待機する時間) group_interval: 5m # 通知を再度送信するまで待機する時間 repeat_interval: 1h receivers: - name: 'test-route' # slackのチャンネル名 slack_configs: - channel: '#general' # email(※slackには表示されなかった) email_configs: - to: "zzz@gmail.com"dockerコンテナ起動
dockerコンテナを起動します
今回は複数コンテナを一度で上げるのにdocker-compose
を使用します$ docker-compose build # "-d"オプションをつけることで、バックグラウンドで実行します # オプションがないとターミナルを閉じた時にコンテナが停止してしまいます $ docker-compose up -d # コンテナの起動を確認 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ab4455256cff prom/prometheus "/bin/prometheus --c…" 5 days ago Up 5 days 0.0.0.0:9090->9090/tcp prometheus 830bf6475888 prom/alertmanager "/bin/alertmanager -…" 5 days ago Up 5 days 0.0.0.0:9093->9093/tcp alertmanager b6fcd4f26f57 prom/blackbox-exporter:latest "/bin/blackbox_expor…" 5 days ago Up 5 days 9115/tcp prometheus_sample_blackbox_exporter_1Prometheusのダッシュボードを確認
http://localhost:9090
にアクセスする
実際の運用ではhttps、ポートフォワーディングなどに対応しますが、今回は開発端末なのでそのままにします
alert_roles.yml
で指定した評価メトリクスを入力し、execute
をクリックすると評価結果をグラフで表示できます
今回はhttpリクエストが成功(200 OK)を評価していて、1.0であれば正常となりますメニューからAlertを選択するとアラート(通知)の状態を確認することができます
状況が色分けされていて、一目でどの評価がエラーとなっているか確認ができますslack通知を確認する
監視対象のURLをありえないURLに変更して、httpレスポンスが500系を返却するようにしてAlertの確認をします
httpリクエストが異常を返却するとAlertメニューの状況が赤く変化しますそして、slackにエラー発生していることが通知されます
今回はSlackというチャットサービスでしたが、チャットの通知に反応する習慣がない人などから「Slackに通知すると気づきにくい!
もっと早く確実に気づきたい」という要望があれば、SaaSの電話コールサービスと繋げることでAlert発生時に電話をコールすることも可能です
通知することが大事ではなく、人間が認識する方法・可能性を考慮した設計にすることが大事だと思っていますおまけ
Prometheusの見た目は正直質素・・・だと思います(必要な機能は揃っているので十分な内容です)が、
「デザインがイケてるダッシュボードにしたい!」という方は、Grafanaと連携させるとかっこよくなると思います
Prometheusと同様にDockerイメージがあるので、docker-compose.ymlに追加することでGrafanaが起動します
興味がある方はぜひチャレンジしてみてはいかがでしょうか「監視を構築するのはかなり辛いなぁ・・・」という方は、
簡単に構築して設定をコード管理できるDocker+Prometheusで監視機能を構築してクリスマスを迎えてはいかがでしょうか?
- 投稿日:2020-12-18T21:20:49+09:00
Docker環境にMySQLを構築してDBを取り込む
概要
Docker環境にMySQLを構築し、SQLデータを流し込む
前提
Dockerがインストールされている状態
ディレクトリ構成
db_sample/ ├ docker/ | └ mysql/ | ├ conf.d/ | | └ my.cnf | ├ initdb.d/ | └ xxxxxx.sql | └ Dockerfile └ docker-compose.ymlファイルの準備
docker-compose.yml作成
db_sample/docker-compose.ymlversion: '3.3' services: db: build: ./docker/mysql # Dockerfileの置き場所を指定 image: mysql:5.7 restart: always environment: MYSQL_DATABASE: sample_db MYSQL_USER: user MYSQL_PASSWORD: password MYSQL_ROOT_PASSWORD: rootpassword ports: - "3314:3306" volumes: - ./docker/mysql/initdb.d:/docker-entrypoint-initdb.d - ./docker/mysql/conf.d:/etc/mysql/conf.d - ./log/mysql:/var/log/mysqlDockerfile作成
db_sample/docker/mysql/Dockerfile
FROM mysql:5.7 RUN touch /var/log/mysql/mysqld.logmy.conf作成
db_sample/docker/mysql/conf.d/my.conf[mysqld] character-set-server=utf8 explicit-defaults-for-timestamp=1 general-log=1 general-log-file=/var/log/mysql/mysqld.log [client] default-character-set=utf8SQLファイルの配置
db_sample/docker/mysql/initdb.d/配下に置く
Dockerコマンド実行
db_sampleディレクトリの配下に移動
$ cd /../db_sample
docker-compose up -d
の実行$ docker-compose up -d Creating network "db_sample_default" with the default driver Building db Step 1/2 : FROM mysql:5.7 5.7: Pulling from library/mysql 6ec7b7d162b2: Pull complete fedd960d3481: Pull complete 7ab947313861: Pull complete 64f92f19e638: Pull complete 3e80b17bff96: Pull complete 014e976799f9: Pull complete 59ae84fee1b3: Pull complete 7d1da2a18e2e: Pull complete 301a28b700b9: Pull complete 979b389fc71f: Pull complete 403f729b1bad: Pull complete Digest: sha256:d4ca82cee68dce98aa72a1c48b5ef5ce9f1538265831132187871b78e768aed1 Status: Downloaded newer image for mysql:5.7 ---> 697daaecf703 Step 2/2 : RUN touch /var/log/mysql/mysqld.log # 指定の場所にログを記録するファイルを作る ---> Running in 7fe949f8a39f Removing intermediate container 7fe949f8a39f ---> f6323d72a74c : : Successfully built f6323d72a74c Successfully tagged mysql:5.7 WARNING: Image for service db was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Creating db_sample_db_1 ... doneCreating db_sample_db_1 ... doneが表示されたら、作成完了
コンテナ起動確認
docker-compose ps
の実行$ docker-compose ps Name Command State Ports ---------------------------------------------------------------------- db_sample_db_1 docker-entrypoint.sh Up 0.0.0.0:3314->3306/t mysqld cp, 33060/tcpコンテナ内のDB接続
コンテナ内にアクセス
$ docker exec -it db_sample_db_1 bash root@55c55b394991:/#MySQL内に入る
パスワードはdocker-compose.ymlのMYSQL_PASSWORDを指定root@55c55b394991:/# mysql -u user -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.7.32-log MySQL Community Server (GPL) Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>MySQLでDB選択とテーブル確認
使用するDBにsample_dbを選択後、テーブル一覧を表示する
mysql> use sample_db Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed # テーブル表示 mysql> show tables; +------------------------------------------+ | Tables_in_sample_db | +------------------------------------------+ | table_01 | | table_02 | : | : | | table_nn | +------------------------------------------+ nn rows in set (0.01 sec)データ確認
mysql> select * from table_01; # table_01のリストが表示される環境削除
コンテナの停止とネットワークの削除
$ docker-compose down Stopping db_sample_db_1 ... done Removing db_sample_db_1 ... done Removing network db_sample_default $dockerイメージ削除
tagが5.7のとの2つが作られているのでIMAGE IDを指定して両方削除$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7 f6323d72a74c 6 hours ago 448MB mysql <none> 697daaecf703 6 days ago 448MB : : $ docker rmi f6323d72a74c Untagged: mysql:5.7 Deleted: sha256:49.... Deleted: sha256:49.... : $ docker rmi 697daaecf703 Untagged: mysql@sha256:d4... Deleted: sha256:697d... Deleted: sha256:521...さいごに
今回は、Docker環境のコンテナにMySQLを構築し、指定場所にあるSQLファイルを実行してテーブル、データ情報を取り込んでみました。
- 投稿日:2020-12-18T19:15:46+09:00
[WIP]Docker+Streama+NFSの構成を試してみた
- 投稿日:2020-12-18T19:13:53+09:00
[WIP]DockerのVolumeにNFSを利用する
- 投稿日:2020-12-18T18:23:15+09:00
Dockerについて
Dockerとは
「コンテナ技術」を用いた
仮想環境
を構築するツール。
Docker社が開発した、オープンソースの人気 No.1ソフトウェア
1つのコンテナとして確立させる為の手間をまとめてるので簡単にコンテナが作れちゃう。Dockerの仕組み
- DockerHub に保存してある
- Dockerイメージ (コンテナ作る為のレシピ)を使い
- Dockerコンテナ を作って
- Dockerエンジン で動かします。
DockerHub ( レジストリ )
Dockerの為のコンテナ共有サービス。ほぼ GitHub 。
① Dockerのイメージがたくさん転がっているので、そこからPull
してコンテナを作ります。( Pullしたイメージを元にrunコマンドでコンテナを作成 )
② 作ったコンテナで開発や作業をし、それをイメージにcommit
する。
③ コミットしたイメージをDockerHubにPush
する事で自分のリポジトリにアップロード。
④ 開発作業などで違うPCでもイメージを使いたいときに、そのアップロードしたイメージをPull
するだけでOK!
Dockerイメージ
コンテナの元となるもの、ひな型、パッケージ。
イメージはいくつかのレイヤと呼ばれるファイルを重ねることで出来ています。
もし欲しいイメージが無かった場合はDockerfileを使い自分でイメージを作ることが出来ます。FROM ubuntu:18.10 #ベースとなるOSの指定 LABEL version="1.0" #Dockerfileのメタ情報(こう言うFileだよと言う情報) LABEL description="Dockerfileのテスト、Apacheサーバー" RUN apt-get update RUN apt-get install -y apache2 #このFileに入るレイヤのインストール CMD ["apachectl", "-D", "FOREGROUND"] #コマンドで上のRUNを起動させている
コマンド 実行内容 FROM ベース(親)画像を指定します。 LABEL メタデータを提供します。 メンテナ情報を含めるのに良い場所です。 ENV 永続的な環境変数を設定します。 RUN コマンドを実行してイメージレイヤを作成します。 パッケージをコンテナにインストールするために使用されます。 COPY ファイルとディレクトリをコンテナにコピーします。 ADD ファイルとディレクトリをコンテナにコピーします。 ローカルの.tarファイルをアンパックできます。 CMD 実行中のコンテナにコマンドと引数を提供します。 パラメータは上書きできます。 CMDは1つだけです。 WORKDIR あとに続く説明の作業ディレクトリを設定します。 ARG ビルド時にDockerに渡す変数を定義します。 ENTRYPOINT 実行中のコンテナにコマンドと引数を提供します。 引数は存続します。 EXPOSE ポートを公開します。 VOLUME 永続データにアクセスして保存するためのディレクトリマウントポイントを作成します。 Dockerコンテナ
Dockerイメージの情報を元に起動された仮想環境
Dockerエンジン
Dockerの心臓、ここがあってのDockerであり、Dockerそのものになります。
コンテナやイメージからくるコマンドをホストOSに伝えて動かす為のもの。3つの要素からなりたっており
• コマンド命令を受け付ける部分
• REST API(ステートレスなデータのやり取り)
• Dockerデーモン(ホストOSとやり取りするところ)
と分かれています。まとめ
これだけ簡単に環境設定が出来て軽くて使い勝手が良いなんて三拍子揃ってるなんて素敵!!
デメリットも色々あるようですが、気軽に使えるから便利!!!
参考
http://docs.docker.jp/v1.12/engine/understanding-docker.html
https://qiita.com/shubatto/items/105f5b90e1cd91ba7c4c
https://blog.codecamp.jp/docker-file-how-to
https://tech-lab.sios.jp/archives/19073
https://knowledge.sakura.ad.jp/13265/
https://www.youtube.com/watch?v=VIzLh4BgKck
- 投稿日:2020-12-18T17:35:31+09:00
Docker環境でMySQLのログを確認する
まず、dockerのMySQLコンテナに入ります。
MySQLサーバにログインして、以下のようにgeneral_log
の位置を確認します。mysql> show variables like 'general_log%'; +------------------+---------------------------------+ | Variable_name | Value | +------------------+---------------------------------+ | general_log | OFF | | general_log_file | /var/lib/mysql/55ca40b8744.log | +------------------+---------------------------------+ 2 rows in set (0.00 sec)
OFF
になっているので、ON
にします。
こうしないとファイルが出現しないようです。mysql> set global general_log = on; Query OK, 0 rows affected (0.01 sec)MySQLからぬけて、
var/lib/mysql
に移動します。ここのファイルの内容を参照すれば見れます。root@55ca40b8744e:~# cd /var/lib/mysql root@55ca40b8744e:/var/lib/mysql# cat 55ca40b8744.log Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock Time Id Command Argument 2020-12-18T17:18:27.044729+09:00 26 Quit先ほど MySQLのサーバを抜けたので、Quitしたと出ています。
試しに
delete
したときのログは以下のように出ます。2020-12-18T17:02:09.716428+09:00 67 Prepare DELETE FROM `TABLE` WHERE `table`.`id` = ? 2020-12-18T17:02:09.716513+09:00 67 Execute DELETE FROM `TABLE` WHERE `table`.`id` = 0
- 投稿日:2020-12-18T15:34:10+09:00
Docker Desktopをupdateしたらコンテナを起動できなくなった話
今まで、dockerのアップデートを忘れていたのですが、久々にアップデートしてみたら、アップデート後、
docker-compose up
で以下の様なエラーが発生。その時の解決策です。ERROR: for node Cannot start service node: Mounts denied: approving /Users/ryota/Library/Mobile Documents/com~apple~CloudDocs/path/to/file: file does not exist ERROR: Encountered errors while bringing up the project.
解決した方法
上記画像の通り、Docker Desktopの
Preferences
を開いた後に、Experimental Features
のタブを選択して、Use gRPC FUSE for file sharing
をOFF
にすれば上手くいきました?ちなみに、バージョンは
3.0.1
でした。
- 投稿日:2020-12-18T15:20:26+09:00
Pleasanter NetCore をDockerで上げる
はじめに
国産OSSとして有名なPleasanterですが、前々から興味があったので、試してみました。
が、セットアップ手順がとても難しく、
簡単に立ち上げられて簡単に壊せる環境が作りたかったので docker-compose で上がるようにしてみました。なお、本記事は私が学習目的で実施した内容で、Pleasanter公式の手順ではない旨ご了承ください。
あと、コメントなどの画像投稿機能が動いていません(ファイルアップロードは動く)。そこら辺分かり次第修正します。実施環境
Windows 10 64bit 上の docker(WSL2) と、
Ubuntu 18.04 64bit 上の docker で動作することを確認しました。コード
https://github.com/yoh1496/Implem.Pleasanter.NetCore/tree/feature/docker
ここに上げてます。
手順
下記手順は上記ブランチをチェックアウトしてから行うのを前提とします。
git clone https://github.com/yoh1496/Implem.Pleasanter.NetCore.git cd Implem.Pleasanter.NetCore git checkout feature/docker
起動
下記コマンドでバックグラウンドに起動できます。
docker-compose up -d
セットアップ
Pleasanterのドキュメントにある CodeDefiner コマンドは下記コマンドで代替できます。
docker-compose exec pleasanter dotnet Implem.CodeDefiner.NetCore.dll <args>
ブラウザで開く
デフォルトでは
5001
番ポートで開けます。簡単?
解説
ちょっと備忘録的にDockerfileを書くにあたり検討した内容を記載します。
マルチステージビルド
# 冒頭 FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build# 末尾 FROM build AS publish RUN dotnet publish "Implem.Pleasanter.NetCore.sln" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish .今回はこんな感じで「マルチステージビルド」というものをしています。
こうすることで、出来上がるイメージには SDK が含まれず軽いイメージができあがります。設定ファイルの分離
volumes: - ./Implem.Pleasanter/App_Data/:/app/App_Data/
docker-compose.yml
内で上記のように App_Data を外出しできるようにしています。「とりあえず」でやってしまったので今後要検証です。永続化?
Pleasanterのデータ保持がどのようになされているのか、まだ理解しきれていないので特に手はつけていません。
postgreSQL を別コンテナに
App_Data のところ ConnectionString が localhost でベタ書きされていたので、
postgres
でベタ書きしました(よくない){ // 略 "SaConnectionString": "Server=postgres;Database=postgres;UID=postgres;PWD=SetSaPWD", "OwnerConnectionString": "Server=postgres;Database=#ServiceName#;UID=#ServiceName#_Owner;PWD=SetAdminsPWD", "UserConnectionString": "Server=postgres;Database=#ServiceName#;UID=#ServiceName#_User;PWD=SetUsersPWD", // 略 }大文字小文字問題
あまり意図がわかっていなくて恐縮ですが、
wwwroot/images
フォルダにHayato*.png
と、hayato*.png
というファイルdotnet publish
では それらは同一ファイルとしてみなされ 小文字のhayato*.png がコピーされない- トップページでは hayato*.png を参照する
というコンボで404が発生してしまったため Hayato*.png を消しています。
https://github.com/Implem/Implem.Pleasanter.NetCore/tree/master/Implem.Pleasanter/wwwroot/images
終わりに
.Net Framework 依存のコードが Implem.Pleasanter 内にあるため、
ビルド時に大量にWarningが発生しますが、手元で動かしている分には普通に動いているようです。
(コメントの画像投稿機能は除く)
- 投稿日:2020-12-18T03:25:49+09:00
Serverless FrameworkでLambdaコンテナイメージを利用する
こちらは、AWS LambdaとServerless Advent Calendar 2020 25日目の記事になります!
クリスマスの公開ですが季節感はないです
悪しからず?はじめに
AWS re:Invent 2020にてLambdaのコンテナイメージのサポートが発表されましたが、
我らが愛するServerless Frameworkでも早々にサポートが行われたので、お試しで使ってみました?
serverless.yml
における定義については、こちらのブログにある通り、<account>.dkr.ecr.<region>.amazonaws.com/<repository>@<digest>
の形式で指定する必要があるそうです
タグでなく、イメージのダイジェストで指定する必要があるとのことなので、sls deploy
時にいい感じに注入する必要があります?作ったもの
以下で公開しています?
https://github.com/yktakaha4/lambda-docker-serverlessなるべく簡単に動作を試せるように、
環境構築からデプロイまでに必要なもろもろをGitHub Actionsにまとめてます
変更すべき箇所はREADMEにまとめていますので併せてご覧くださいポイント
Dockerファイルは、
public.ecr.aws/lambda/xxxxx
から作成する必要があるそうです
こちらにてベースイメージが公開されています?あと、従来は
serverless.yml
にて関数のエントリーポイントを設定していたものと思いますが、Dockerfileにて設定しておく必要があるようです
個人的に、ECSのScheduled Taskで単一のコンテナに複数の関数を含めて、定義ごとに動かすものを変えるということをやっていたのですが、現状だと個別にビルドしておく必要がある感じなのでしょうか...?DockerfileFROM public.ecr.aws/lambda/nodejs:12 AS builder WORKDIR /opt/build COPY . . RUN npm ci RUN npm run build ##### ##### ##### ##### FROM public.ecr.aws/lambda/nodejs:12 AS runner COPY --from=builder \ /opt/build/package*.json \ ./ COPY --from=builder \ /opt/build/dist \ ./dist RUN npm ci --only=production # !!! ここポイント !!! CMD ["dist/index.handler"]イメージのビルドとECRへのプッシュが済んだら、イメージのダイジェストを取得し、
sls
コマンドに渡せるように環境変数に設定します
従来のset-env
は現在無効となっているので、新しい書き方でやってますあと、今回初めて知ったのですが、GitHub Actionsの環境にはデフォルトで
aws
コマンドがインストールされてるんですね...!deployment.yml(抜粋)jobs: deploy: runs-on: ubuntu-18.04 timeout-minutes: 300 steps: # 略 # ECR - uses: aws-actions/amazon-ecr-login@v1 id: login-ecr - run: | docker build -t $REGISTRY/$REPOSITORY:$TAG . docker push $REGISTRY/$REPOSITORY:$TAG # !!! ここポイント !!! echo "IMAGE_DIGEST=$(aws ecr describe-images --repository-name $REPOSITORY --image-ids imageTag=$TAG --output text --query 'imageDetails[0].imageDigest')" >> $GITHUB_ENV env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} REPOSITORY: lambda-docker-serverless-repos TAG: latest # Serverless Framework - run: npm ci - run: npm run deploy env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} IMAGE_DIGEST: ${{ env.IMAGE_DIGEST }}
serverless.yml
では、従来handler
を使っていたところを、image
でコンテナを指定します
#{AWS::AccountId}
など、シャープで始まるものは serverless-pseudo-parametersの働きにより実値が埋め込まれますserverless.ymlservice: lambda-docker-serverless provider: name: aws stage: prod region: ${env:AWS_DEFAULT_REGION} deploymentBucket: lambda-docker-serverless-deployment functions: index: # !!! ここポイント !!! image: "#{AWS::AccountId}.dkr.ecr.#{AWS::Region}.amazonaws.com/lambda-docker-serverless-repos@${env:IMAGE_DIGEST}" events: - http: path: index method: post cors: true plugins: - serverless-pseudo-parameters今回は、こんなシンプルな関数を作ってみました
リクエストで受け取った名前を大文字にして、挨拶を返す処理になります?index.tsimport { APIGatewayProxyHandler } from "aws-lambda"; import "source-map-support/register"; interface Request { name?: string; } export const handler: APIGatewayProxyHandler = async (event) => { try { const { name } = JSON.parse(event.body ?? "{}") as Request; return { statusCode: 200, body: JSON.stringify({ message: `Hello, ${(name ?? "nanashi-san").toUpperCase()} !`, }), }; } catch (e) { return { statusCode: 500, body: JSON.stringify({ error: String(e), }), }; } };
https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/index
にアクセスしてみます
Insomniaで実行してみると、ちゃんと動いてそうでいい感じです!おわりに
当初は、関数内でPuppeteerを動かそうと少し試していたのですが、
従来の一番安定したやり方だったchrome-aws-lambdaを使うよりも楽に構築できると思いきや、ライブラリの不足やディレクトリの権限周りの問題で結構留意することが多かったので諦めました...
(ちなその残骸はこちらにあります⚰️)従来実行環境の微妙な差異に悩まされることもちょいちょいあったように思いますが、
今後コンテナベースの環境で開発ができるようになると利便性が上がるので、引き続き動向を追っていきたいですね????