docker for windows で docker pull に失敗する場合の対処方法
docker for windows にて docker pull
に失敗する場合の対象方法について
dockerイメージを取得しようとすると下記のエラーが出た
$ docker pull debian Using default tag: latest Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
docker for windows バージョン情報
dockerのバージョン
$ docker -v Docker version 17.03.1-ce, build c6d412e
対処方法
Settings > Network の項目にて
DNS Server の項目で Fixed
にチェックを入れ、値を 8.8.8.8
にする
参考
.NET Core コンソールアプリで日本語出力する方法
Windowsでコンソールアプリを作成し実行すると日本語が文字化けする。
Consoleの出力文字コードがUTF8固定になっていることが問題の様です。
対応方法
NuGetから
System.Text.Encoding.CodePages
をインストールするMain関数の先頭に下記を追加
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
こんな感じ
static void Main(string[] args) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); }
参考
AWSのEC2に自動デプロイする(github+circleci+CodeDeploy)
githubにpushしたとき、自動でデプロイし、失敗した場合はslackに通知する設定方法のメモです。
期待する動作
- githubにpush
- circleciでビルド
- CodeDeployでデプロイ
- もしデプロイに失敗したらslack通知
設定するもの
- s3
- EC2
- CodeDeploy
- circleci
- SNS
- lambda
デプロイ用s3バケット
デプロイ時のリビジョン保存用のバケットを用意する
EC2
- CodeDeploy Agentのインストール
- EC2用ロール
インスタンス
CodeDeployができるOSは以下
- AmazonLinux
- Red Hat Enterprise Linux
- Ubuntu Server
- Microsoft Windows Server
EC2でインスタンスの作成を選択したとき、クイックスタートで選択できるOSの様な気がします。
IAM
下記の権限を持つIAMをアタッチする
- AWSCodeDeployFullAccess
- AmazonS3ReadOnlyAccess
CodeDeploy Agentのインストール
EC2内で実行
sudo yum update sudo yum install aws-cli -y cd /home/ec2-user aws s3 cp s3://aws-codedeploy-ap-northeast-1/latest/install . --region ap-northeast-1 chmod +x ./install sudo ./install auto
CodeDeployの設定
- appspec.yml
- CodeDeploy用ロール
appspec.yml
デプロイ時の設定として appspec.yml
が必要です。
appspec.yml
は、gitで管理してるアプリのルートディレクトリに置きます。
appspec.yml のサンプル
version: 0.0 os: linux files: - source: / destination: /var/www/campaign-app hooks: BeforeInstall: - location: scripts/BeforeInstall.sh AfterInstall: - location: scripts/AfterInstall.sh timeout: 300 runas: root ApplicationStart: - location: scripts/ApplicationStart.sh timeout: 300 runas: root ValidateService: - location: scripts/ValidateService.sh timeout: 300 runas: root
BeforeInstall
や AfterInstall
など、各処理が実行される順番については↓に詳しく書いてありました。
dev.classmethod.jp
CodeDeploy用ロール
ポリシー AWSCodeDeployRole
を持つロール
githubとcircleciの連携
- circle.yml
- circleci用IAM
circle.yml のデプロイメント部分
deployment: deploy: branch: master # デプロイ対象にするブランチ名 codedeploy: # circleciでCodeDeployを使う codedeploy-aplication-name: # CodeDeployのアプリケーション名にする application_root: / region: ap-northeast-1 revision_location: revision_type: S3 # デプロイ履歴のソースコードをs3に保存する s3_location: bucket: bucket-name # デプロイ履歴のソースコードを保存するbucket名 key_pattern: {BRANCH}-{SHORT_COMMIT}.zip # 保存時のファイル名 deployment_group: all
CodeDeployではデプロイしたアプリを圧縮してs3に保存することができるので、s3へ保存するファイル名を決める必要があります。
ファイル名は
key_pattern: {BRANCH}-{SHORT_COMMIT}.zip
の用に定義することができます。
パラメータ | 意味 |
---|---|
BRANCH | デプロイするbranch名に変わる masterブランチなら master となる |
SHORT_COMMIT | デプロイ時のcommitIDになる |
circleciに設定するIAM
- AWSCodeDeployFullAccess の権限をもつIAM
デプロイ失敗時の通知設定
- SNS
- lambda function
設定方法
SNS
- トピックを作成する
CodeDeploy
- CodeDeployの設定でトリガーに 1.で作成したSNSを追加する
失敗時の通知をしたいので、イベントは Deployment fails
lambdaの設定
項目 | 設定 |
---|---|
設計図の選択 | sns-message |
トリガーの設定 | 作成したSNSトピック |
'use strict'; // Ref: https://gist.github.com/vgeshel/1dba698aed9e8b39a464 console.log('Loading function'); const https = require('https'); const url = require('url'); // to get the slack hook url, go into slack admin and create a new "Incoming Webhook" integration const slack_url = "{slackのwebhookurl}"; const region = 'ap-northeast-1' const codedeploy_url = 'https://' + region + '.console.aws.amazon.com/codedeploy/home?region=' + region + '#/deployments/' const slack_req_opts = url.parse(slack_url); slack_req_opts.method = 'POST'; slack_req_opts.headers = {'Content-Type': 'application/json'}; exports.handler = function(event, context) { (event.Records || []).forEach(function (rec) { if (rec.Sns) { var req = https.request(slack_req_opts, function (res) { if (res.statusCode === 200) { context.succeed('posted to slack'); } else { context.fail('status code: ' + res.statusCode); } }); req.on('error', function(e) { console.log('problem with request: ' + e.message); context.fail(e.message); }); var message = JSON.parse(rec.Sns.Message); var str = '*' + 'Application: ' + message.applicationName + ' deploymentGroupName: ' + message.deploymentGroupName + ' deploymentId: ' + message.deploymentId + '*' + ' ' + codedeploy_url + message.deploymentId; req.write(JSON.stringify({text: str})); // for testing: , channel: '@vadim' req.end(); } }); };
その他
Railsアプリをデプロイする時にハマったことがありました。
詳しくは調べてませんが、下のような順番でデプロイしてるんじゃないかなと思ってます。
- circleciでビルドした結果を圧縮し、s3にデプロイ
- s3から各EC2へソースコードをデプロイ
ここで問題になるのが、 circleci内で bundle install
した結果をそのままEC2にデプロイするということです。
ビルド環境(circleci)で bundle install
したときのパスがそのまま設定されているため、EC2インスタンスとcircleciのビルド時の環境が違うと、パスが通らないことが有りアプリの起動に失敗します。
解決策としては、CodeDeployでアプリ起動前に bundle install
をすることです。
bundle install --path ../vendor/bundle
の様な形で、デプロイするソースコード外にインストールする方法で回避しました。
参考
[公式チュートリアルではじめる]CircleCI+CodeDeployを使ったCD(継続的デプロイ) | Developers.IO
CircleCI、CodeDeploy、S3を使って、GitHubにpushしたらEC2にデプロイされる仕組みを作る - Qiita
CodeDeployのApplicationStopイベントフックはどう実行される? | Developers.IO
Amazon Web Services ブログ: AWS CodeDeployがアジア・パシフィック(東京)で利用可能になりました
AWS CodeDeployのデプロイ結果をSlackに流す | mediba Creator × Engineer Blog
TypeScriptでReactを書くときはStateのパラメータに?を付ける
TypeScriptでReactを書いているとき、Stateに複数パラメータを用意した時に ?
を付けてオプションパラメータにします。
そうしないと、setState の更新時に全てのパラメータを更新しないといけなくなります。
なので、必ず付けろというよりは、パラメータを一つだけ更新したいときにはこうしたほうが良いという話でした。
もうちょっと詳しく
こんな感じで年齢と身長を表示するコンポーネントがあったとします。
import * as React from 'react'; interface IPersonProps { } interface IPersonState { age: number; height: number; } /** * Person */ export class Person extends React.Component<IPersonProps, IPersonState> { constructor(props: IPersonProps) { super(props); this.state = { age: 0, height: 0 } } render() { return ( <div className="person"> <div>年齢 : { this.state.age }</div> <div>身長 : { this.state.height }</div> </div> ); } }
ここで、身長のみを更新するイベントを追加しようとしたとき下記のように書きたくなります。
handleOnChangeHeight = (height: number) => { this.setState({ height: height }); }
ですが、この場合はコンパイル時エラーになります。
理由は↓です。
interface IPersonState { age: number; height: number; }
パラメータがオプションになっていないため両方更新しないといけなくなります。
なので、 ?
を付けてオプションパラメータにしてあげます。
interface IPersonState { age?: number; height?: number; }
そうすることで、 setState
時に更新したいパラメータだけを更新することができます。
sendgrid-phpで添付画像を付けてメール送信する方法
phpでメール送信する方法の一つとしてSendGridがあります。
添付ファイルを付けてメール送信する方法についてのメモです。
※ 前提として、composerを使用して、sendgrid-phpをインストールしているものとします
テキストのみのメール
<?php require_once "vendor/autoload.php"; $from = new SendGrid\Email("name", "email@example.com"); $subject = "件名"; $personalization = new SendGrid\Personalization(); $personalization->addTo(new SendGrid\Email(null, "send@example.com")); $personalization->setSubject($subject); $content = new SendGrid\Content("text/plain", "本文"); $mail = new SendGrid\Mail(); $mail->setFrom($from); $mail->addPersonalization($personalization); $mail->setSubject($subject); $mail->addContent($content); $sg = new \SendGrid("sendgridApiKey"); $response = $sg->client ->mail() ->send() ->post($mail);
テキスト+添付画像のメール
<?php require_once "vendor/autoload.php"; $from = new SendGrid\Email("name", "email@example.com"); $subject = "件名"; $personalization = new SendGrid\Personalization(); $personalization->addTo(new SendGrid\Email(null, "send@example.com")); $personalization->setSubject($subject); $content = new SendGrid\Content("text/plain", "本文"); $mail = new SendGrid\Mail(); $mail->setFrom($from); $mail->addPersonalization($personalization); $mail->setSubject($subject); $mail->addContent($content); // 添付ファイル $filePath = "path/to/file"; $attachment = new SendGrid\Attachment(); $handle = fopen($filePath, "rb"); $contents = fread($handle, filesize($filePath)); $attachment->setContent(base64_encode($contents)); $attachment->setFilename("filename.png"); $fileInfo = new FInfo(FILEINFO_MIME_TYPE); $attachment->setType($fileInfo->file($filePath)); $mail->addAttachment($attachment); $sg = new \SendGrid("sendgridApiKey"); $response = $sg->client ->mail() ->send() ->post($mail);
テキストメール送信の処理に対して追加したのは下記コードです。
処理としては、ファイルをバイナリで開いてBase64変換することだけです。
調べると、ファイルパスとファイル名を渡すと送信できるような記述が多くてハマりました。
// 添付ファイル $filePath = "path/to/file"; $attachment = new SendGrid\Attachment(); $handle = fopen($filePath, "rb"); $contents = fread($handle, filesize($filePath)); $attachment->setContent(base64_encode($contents)); $attachment->setFilename("filename.png"); $fileInfo = new FInfo(FILEINFO_MIME_TYPE); $attachment->setType($fileInfo->file($filePath)); $mail->addAttachment($attachment);
その他
テキストメールの改行が無視される
テキストメールを送信したときに、改行が無視されてしまうことがありました。
SendGridのダッシュボードから、テキストメールはそのまま送信するように設定すれば解決しました。
メール送信時のステータスコード確認
上記のソースコードで送信後に下記を実行することでステータスコードを取得できます。
$response->statusCode()
200や202などがメール送信成功時に返ってくるステータスコードの様です。
参照
AWS CloudWatch Logs で選択可能なOSについて
以前は debian にインストールできなかった、 AWS cloudlogs のインストール可能なOSが増えていました。
regionの選択肢も増えて、アジアパシフィック (東京) ap-northeast-1
も選択できるようになっていました。
もともとは下記方法でawslogsを使おうとしてました。
いつもは、debianを使うのでubuntuにするしかないかなと思ってました。
setupスクリプト
https://s3.amazonaws.com/aws-cloudwatch/downloads/awslogs-agent-setup-v1.0.py
インストール可能OS
https://hub.docker.com/r/takipone/docker-awslogs/~/dockerfile/
dockerfileでは
ADD awslogs.conf.dummy ./awslogs.conf
と書いてあって、dummyって何だろうと思ったけど、githubのRepositoryを見たら、ファイルがありました。
そして、こちらに記載されているものがインストール可能OSと出力先のリージョンが増えたものです。
setupスクリプト
https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py
インストール可能OS
せっかくなので、githubにDockerfileをpushして、dockerhubでビルドしてみました。