- 投稿日:2020-01-03T23:24:14+09:00
Dockerでlaravelの開発環境構築をした (php-pfm,nginx, mysql) 2019
おはようございます。
タイトルの通りに今日はDockerでlaravelの環境構築経験を述べたいと思います。
私はまだ日本語を勉強中なので。わかりにくいことがあれば申し訳ありません。
2017に同じ内容の記事を投稿しました:https://qiita.com/mytv1/items/f26cd77f2801357dee8f
それでも最近また触りたいと思って、触ってみたらLaravelのバージョンが古くなったとわかりました。新しいパッケージを結合できるように更新したいというきっかけで再度記載します。よろしくお願いします。
ホストの情報
OS
MacOS High Sierra 10.13.6
Docker
$docker -v Docker version 19.03.5, build 633a0eaDocker Compose
$docker-compose -v docker-compose version 1.24.1, build 4667896b構築する予定の環境情報
Webserver
Nginx 1.0
Database
mysql 8.0
PHP
PHP:7.4-FPM
構成
構築終わったら構成が下記だと想定します。
|-- app # Laravelを格納するDockerコンテナ |-- composer # Composerを格納するDockerコンテナ(PHPのcomposerです!) |-- db # データベースを格納するDockerコンテナ |-- docker-compose.yml |-- web # ウェブサーバーを格納するDockerコンテナディレクトリ構成と実際動いている構成と下記のように関係があると思います。
app、web、dbはそれぞれのコンテナと該当します。処理フローと言えば、最初にリクエストはWebコンテナに渡されて、その後WebコンテナからAppコンテナに引き渡します。ここにもし必要であればAppコンテナはDatabaseコンテナとクエリーでやりとりして、その結果を処理してからWebコンテナにレスポンスに返し、最後にブラウズに返却します。
構築手順
1.プロジェクトを作成
1.1.新規ディレクトリを作成
ゼロから作成ということで、新規ディレクトリを作成します。名前について私は「docker_laravel_2019」と選びますが、任意です。
$ mkdir docker_laravel_2019 $ cd docker_laravel_20191.2.Laravelプロジェクトを新規作成
https://laravel.com/docs/6.x/installation#installing-laravel
Laravelの公式サイトによると作成するにはComposer経由という選択肢がありますね。
私もComposer経由で作成しますが、そのComposerをホストPCにあるComposerではなく、Dockerコンテナとして新規作成します。理由はホストPCでComposerとPHPのバージョンを管理するのはDockerで管理と比べてちょっと手間ということです。PHPのバージョン、Composerのバージョンを上げたり、下げたり調整するMacosの手順のはちょっと面倒かもしれませんね。
簡単な場合はDockerなら記載し直したらいけると思います。1.2.1. Composerディレクトリを作成
$ mkdir composer1.2.2. ComposerのDockerイメージを作成
https://github.com/mytv1/docker_laravel_2019/blob/master/composer/composer.dockerfile
composer/composer.dockerfile
FROM php:7.4-fpm RUN apt-get update && apt-get install -y libzip-dev # Extension zip for laravel RUN docker-php-ext-install zip # Install composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer RUN composer global require laravel/installerベースのイメージは最新のphpバージョンの7.4を選びました。その後はcomposerインストールまたはComposerでlaravelプロジェクトを作成するのに必要なライブラリ(zip)をインストールします。
最後はコマンドの
RUN composer global require laravel/installerはLaravelのインストーラーをインストールします。1.2.3. ComposerのDockerイメージをビルド
これまでComposerのDockerイメージを作成しました。次はコンテナになるようにビルドします。
$ docker build -t localcomposer -f ./composer/composer.dockerfile ./composer・
-t localcomposer: イメージの名前というか、タグをlocalcomposerとします。実行するとインストールするのに数分がかかるかもしれません。
1.2.4. ComposerコンテナでLaravel初期プロジェクトを作成
$ docker run -it -v $(pwd):/var/www/html localcomposer:latest /root/.composer/vendor/bin/laravel new app・
-v $(pwd):/var/www/html:ホストのカレントディレクトリをコンテナの/var/www/htmlとマウントします。その新規のプロジェクトが/var/www/htmlに作成がされるので、それをコンテナと一緒に消さないようにホストに残すようにするということです。
・app:作りたいLaravelプロジェクトの名前、appとします。実行終わったら、ディレクトリは下記のようになりますね。
|-- app |-- composer |-- composer.dockerfile1.3. NginxのDockerコンテナを構築
1.3.1. 新規ディレクトリを作成
$ mkdir web1.3.2. Nginxの設定を作成
web/vhost.confを作成
https://github.com/mytv1/docker_laravel_2019/blob/master/web/vhost.conf
server { listen 80; index index.php index.html; root /var/www/public; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; proxy_set_header HTTP_AUTHORIZATION $http_authorization; location / { try_files $uri /index.php?$args; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; sendfile off; } }その中にある数点を説明させていただきます。
*listen 80: 80ポートに聞き耳を立てる
*fastcgi_pass app:9000: FastCGIサーバーのアドレスを指定します。WebサーバーのNginxがリクエストを受けた後はFastCGI(Laravel)に引き渡します。そのアドレスはここにしています。appはホスト名で、後でdocker-compose.ymlに記載されます。9000はデフォルトのポートですね。NginxのDockerイメージを作成
web/web.dockerfileを作成https://github.com/mytv1/docker_laravel_2019/blob/master/web/web.dockerfile
FROM nginx:1.10 ADD vhost.conf /etc/nginx/conf.d/default.confベースイメージはnginx:1.10にします。Nginxの設定はホストのvhost.confから
ADDでコポーします。これまで構成は下記になりますね。
|-- app |-- composer |-- web |-- vhost.conf |-- web.dockerfile1.4. MysqlのDockerコンテナを構築
1.4.1. 新規ディレクトリを作成
$ mkdir db1.4.2. mysql設定を作成
./db/my.cnfを作ります
https://github.com/mytv1/docker_laravel_2019/blob/master/db/my.cnf
[mysqld] default-authentication-plugin = mysql_native_password今度私が使うイメージは
mysql:8.0で、デフォルト認証方法は普通のパスワードの認証ではなく、caching_sha2_passwordという認証仕方になります。そのままだとlaravelの一般的な認証はいけませんので、mysqlの設定に通常の認証設定に変更します。mysqlのDockerコンテナは公式な既存のイメージを使います。Nginxのように私は継続し新規で作成しません。ただ設定を上書きます。
これまで構成は下記になります。
|-- app |-- composer |-- web |-- db |-- my.conf1.5. LaravelのDockerコンテナを構築
1.5.1. Dockerイメージを作成
./app/app.dockerfileを作ります。
https://github.com/mytv1/docker_laravel_2019/blob/master/app/app.dockerfileFROM php:7.4-fpm RUN apt-get update && apt-get install -y libzip-dev # Extension mysql driver for mysql RUN docker-php-ext-install pdo_mysql mysqliComposerのDockerイメージのように、ベースイメージをphp:7.4-fpmにします。その他はpdoまたmysqlドライバーのライブラリをインストールします。
1.5.2. Laravelに必要なパッケージをインストール
$ docker run -v $(pwd)/app:/var/www/html localcomposer:latest composer installまた前述で作成したcomposerのDockerコンテナでインストールします。
1~2分ぐらいかかるかもしれません。1.5.3. 環境変数を編集
下記のように
./app/.envを編集します。DB_HOST=127.0.0.1 DB_PASSWORD=↓
DB_HOST=database DB_PASSWORD=secret・
DB_HOST: Laravelから見るデーターベースのホストを指定する場所です。通常はホストで同じで配置されて、127.0.0.1でいいですが、今度はDockerコンテナの間で繋がるということで、ホスト名はDockerコンテナの名称になります(デフォルト該当するネットワーク名はDockerコンテナの名になるでしょう)・
DB_PASSWORD: rootとしてログインするパスワードです。この「secret」は後でdocker-compose.ymlで宣言します。これまでディレクトリの構成は:
|-- app |-- .... |-- .env |-- app.dockerfile |-- .... |-- composer |-- web |-- db1.6. docker-composer.ymlを作成
docker-compose.ymlはそれぞれのコンテナをモータニングする手順を記載するファイルですね。私は下記のように設定します。
./docker-compose.ymlを作るhttps://github.com/mytv1/docker_laravel_2019/blob/master/docker-compose.yml
version: '3' services: # The Application app: build: context: ./app/ dockerfile: app.dockerfile working_dir: /var/www volumes: - ./app/:/var/www/ # The Web Server web: build: context: ./web/ dockerfile: web.dockerfile working_dir: /var/www volumes: - ./web/:/var/www/ - ./app/public:/var/www/public ports: - 8080:80 # The Database database: image: mysql:8.0 volumes: - ./db/dbdata:/var/lib/mysql - ./db/my.cnf:/etc/mysql/conf.d/my.cnf command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci','--default-authentication-plugin=mysql_native_password'] environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: secret ports: - "33061:3306" volumes: dbdata:今まで作成していたコンテナの名称の通りに、それぞれのコンテナをここに記載します。
app: LaravelのDockerコンテナ、ホストのappをコンテナの/var/wwwとマウントします。開発する時にホストで修正するとすぐにコンテナに反映するようにするためです。web: NginxのDockerコンテナdatabase: DatabaseのDockerコンテナこれまでディレクトリの構成は:
|-- app |-- composer |-- web |-- db |-- docker-compose.yml2.システムを立ち上げる
これまで構築は終わると思います。実行してみましょう〜
$ docker-compose up立ち上がる1分ほど、http://0.0.0.0:8080で下記の表示が出ると想定します。
これまで構築が終わります!機能開発はこれから開始されると思います。
その他
上記のインデックスページが出るということはまだLaravelがデータベースと繋がらない可能性があります。
確認するために、マイグレーションを実行してみます。$docker-compose exec app php artisan migrate --seedデフォルトはlaravelは認証用のテーブルのマイグレーションが用意されますん。実行するとこういうテーブルが作られますね。ついでにダンプデータも作ります(seed)。実行結果はこんな感じです。
Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.04 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.03 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds) Database seeding completed successfully.無事に実行できたら、繋がることは大丈夫だと思います〜
3.ソースコード
https://github.com/mytv1/docker_laravel_2019
この記事に利用する設定、コードをgithubに上げました。ご参考になればと思います。
お終い
これまでお疲れ様でした〜
この記事は皆の作業に役に立てば嬉しいです。m(_ _)m
- 投稿日:2020-01-03T19:22:50+09:00
4年ぶりにエンジニアに戻った人の話
こんにちは、Qiita初投稿です。
色々あって昨年末に4年間勤めていた外資系のゲーム会社でのプロデューサー業を辞めてエンジニアに戻りました。
前職ではエンジニアではなく、翻訳やアカウントマネージメント系の仕事などをやっていました。
エンジニアブログを書く前に、今回は元エンジニアが4年間経ってエンジニアに戻って世界が一変していた、浦島太郎のような話をしたいと思います。経歴:
2011年: 大手企業に新卒でエンジニア就職
秋入社というのもありまさかの新卒唯一の日本人、まわりは中国人とインド人ばっかり。入社一日目でエンジニア職人気なさすぎオワタと思う。まわりのエンジニアが毎月行われれていた深夜作業に駆り出されていくのを怯える毎日(結局一度もその作業をすることはなかったが)
2013年: ベンチャー企業へ転職
前職ではテスト業務しか触れず、いつの間にかポジションもQAエンジニアになってしまったのでエンジニアらしいことがしたいと一念発起して、当時黎明期だったモバイルアプリ業界へ転職。たまたま入社直後にアプリがヒットし、会社が急成長。カスタマーサポート担当→QAエンジニア→サーバーエンジニアと役割を変え、気づいたらエンジニアリードになっていった。
2015年: 外資系ゲーム会社へ転職
ヘッドハンティングで当時日本サーバーを建てようとしていた世界的人気のゲームを運営する会社へ入社。エンジニアではなく語学力+QA経験でLocalization QAを任される。そのうち、「君これもできるよね?」というノリでユーザーコミュニケーション担当をやっていたら、そちらが本業になりLocalizationチームから外れてMarketingチームへ異動。Abemaでテレビ番組のプロデューサーをやっていたら、半年で今度は当時のesports担当が外れたので急遽、責任者に就任。
2019年: 現在の会社へ
前職を8月末に辞表を出し11月末に退社(理由は色々あったので割愛)。就職先を決めていなかったので、「いい機会だし色んな業界の話を聞いてみよう」と多くの会社に面接に行っていたら現在の社長と意気投合、はれて4年ぶりにエンジニアに復職。
エンジニアに戻ってきて
前置きが長くなってしまいましたが、ここからが本題。まず転職時の感想ですが。
エンジニア職が好待遇に
昔はエンジニア職といえば3K(Kitsui, Kitanai, Kaerenai)のイメージが強かったです。実際「え、エンジニアなんてやってるんですか?」と大学時代の知り合いに言われたぐらいで、エンジニアなんてさっさとやめてマネージメントに入るのが勝ち組なんて影では言われていました。
正直直近の転職活動の時も、最初は「エンジニア戻るのはないなー」と思って、それでも経歴上エージェントから話が来るので渋々話を聞きにいっていたのですが。
…あれ?エンジニア職の待遇変わってね?
聞くと、今IT系エンジニアの求人倍率は10倍なんですね。昔は「私の代わりはいくらでもいるもの」という感じだったのですが、みんなどこへ行ってしまったのか…当然ながら給与も想像より上、同じように応募した翻訳やプロデューサー業よりも上でした。
技術の進歩
エンジニアに4年ぶりに戻るとあって、有給消化中はほぼ毎日10時間ぐらい今の技術を勉強に費やしていました。
完全にキャッチアップとはまだまだ遠いですが、思ったことを簡単に書くと、サーバーインフラ構築が簡単に
本当にこれ、当時(2013年ぐらい)だとAWSのEC2とS3とCloudFront使ってサーバーエンジニアが汗と涙で毎回デプロイしてたのに、DockerとEBS組み合わせたら何も考えずにサーバーが建てられる、しかもコンテナモデルだからデプロイが速い速い。あとサーバーレスアーキテクチャを使ったマイクロサービスとか、昔だったらEC2の別サーバーでバッチ処理させるしかなかったのに、凄い(求: 語彙力)
Javascriptって便利じゃない?
昔のJavascriptには何度泣かされたことか。しかしいざ、Vue.js触ってみて思ったのが「これ以外の言語で非同期処理って書けるの?」とまで思わされてしまうほど、Javascriptが使える言語になっていたのに驚き。
でも言語仕様はやっぱり好きじゃないPythonが主流言語に
これが地味に一番嬉しい。大学で時代を先取りしすぎた教授たちに「明日から課題はPythonで提出して」(当時はJavaで提出していた)と言われかれこれ10年以上Pythonを使っているのに、日本でPythonを使うのはスクリプト処理の時ぐらい。サーバーはRuby on Railsだったのも今は昔、若手のエンジニアから「RoR使ってるのは30代後半のおっさん」と言われ軽くショックを受けました。…ええそのせいもあって、弊社はDjangoでサーバー書いてます。
最後に
ここまでつらつらと書きました。エンジニアに戻ってまだ日も浅いのでまだまだわからないことが多いのですが、4年ぶりに戻ってきて思っていることは
エンジニアは雇うから、育てる職種に
エンジニアの待遇が良くなったという反面、優秀なエンジニアを採用するというのが本当に難しい時代になったと思います。反面、今までのような技術的なハードルは下がってきているので、きっちりと育てることのできるエンジニアをいかに採用し戦力としていくことが重要に思えます。エンジニアマーケットのグローバル化
Pythonなどの言語が主流言語として台頭してくる中で、多くのドキュメントなどのリソースは英語で書かれており、海外には多くのコミュニティも存在します。そのため、日本語だけだと最先端の技術を取り込んでいくための情報量に限りがあります。10年ぐらい前からも言われていることですが、エンジニアとして今優先すべきは英語での語学力だと思っています。合わせて、採用も日本人だけでなく海外の技術者を取り込んでいくことが重要なファクターとなると考えています。2をふまえて、今の会社でのエンジニア採用は「英語のみ可」に入社後に変更し、社内での英語の義務化を導入するか目下検討しています。1は会社のフェーズとして育てられる環境がないのでまだできていませんが、組織が安定してき次第取り掛かりたいと思っています。
ではでは
- 投稿日:2020-01-03T17:35:32+09:00
ラズパイ4にdocker,docker-composeをインストール
Docker
# dockerをインストールする $ curl -sSL https://get.docker.com | sh # pi,dockerユーザに docker コマンドが使えるように権限を与える $ sudo usermod -aG docker pi # ここで一度ラズパイをリブートする # dockerがインストールされたかを確認する $ docker -v Docker version 19.03.5, build 633a0ea # dockerが動くかテストする $ docker run hello-world # ラズパイ起動時にdockerも起動するように設定 $ sudo systemctl enable dockerdocker-compose
# docker-composeをインストールするための依存関係のものを先にインストールする $ sudo apt-get install libffi-dev libssl-dev $ sudo apt-get install -y python3 python-pip3 # docker-composeをインストールする $ sudo pip3 install docker-compose # docker-composeがインストールされたかを確認する $ docker-compose -v docker-compose version 1.25.0, build b42d419参考
Installing Docker and Docker Compose on the Raspberry Pi in 5 Simple Steps - DEV Community ????
Install Docker and Docker-Compose on your Raspberry Pi - Jonathan Meier
- 投稿日:2020-01-03T16:40:20+09:00
x509: certificate signed by unknown authority の対応
目的
Dockerfileに
go getしようとすると、↓このようなエラーが発生してたので、解決法をメモ
x509: certificate signed by unknown authority調べた結果、
go getやnpmはSSLを経由して実行しています。なので、証明書をdockerに食わせないといけない。解決方法
OSの
cafile.pemをDockerfileにコピーしますCOPY cafile.pem /usr/local/share/ca-certificates/ RUN apk add --no-cache ca-certificates && \ update-ca-certificates※
hoge.pemはオレオレ証明書生成できると思う
参考:
http://rikuga.me/2017/12/24/oreore-ca-and-ssl-cert/
https://qiita.com/ll_kuma_ll/items/13c962a6a74874af39c6コード
一応簡単なgitコードはこちらになります。
- 投稿日:2020-01-03T15:49:51+09:00
GoのS3 ListObjectsはPythonより20秒遅いのか?問題
はじめに
S3から大量Objectをダウンロードする場合、Objectサイズに関わらず中々速度が出ないですよね。
Pythonで書いている時も、concurrent.futuresなどで頑張ってたのですが、もしかしてGoroutineで出来るのでは?と思い、Golangデビューしてみました。やろうと思ったこと
- ListObjectV2を用いて、S3の特定Prefix配下のKeyをすべて取得
- 取得したKeyをGoroutineでいい感じにダウンロード
実際起こったこと
- ListObject部分を試しに書いてみたが、はっきり言って遅い。
- なんならPythonで書いた方が早い気が?
ん?API叩くだけなので同じ速度。だったらまだ納得は出来るが、スクリプト言語よりGoの方が遅いというのはちょっと気になる。
予定を急遽変更して、本件を少し検証してみました。ソースコード
Go版
main.gopackage main import ( "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "os" ) func main() { bucket := os.Getenv("BUCKET") prefix := os.Getenv("PREFIX") region := os.Getenv("REGION") sess := session.Must(session.NewSession()) svc := s3.New(sess, &aws.Config{ Region: ®ion, }) params := &s3.ListObjectsV2Input{ Bucket: &bucket, Prefix: &prefix, } fmt.Println("Start:") err := svc.ListObjectsV2Pages(params, func(p *s3.ListObjectsV2Output, last bool) (shouldContinue bool) { for _, obj := range p.Contents { fmt.Println(*obj.Key) } return true }) fmt.Println("End:") if err != nil { fmt.Println(err.Error()) return } }Python版
こちらもサクッと書いてみる。
Goと条件を合わせる為、低レベルクライアントで。main.py#!/usr/bin/env python # -*- coding: utf-8 -*- import os import boto3 bucket = os.environ["BUCKET"] prefix = os.environ["PREFIX"] region = os.environ["REGION"] # r = boto3.resource('s3').Bucket(bucket).objects.filter(Prefix=prefix) # [print(r.key) for r in r] # 普段は上記の様に取得するが、Golangへ寄せるため下記のコードにて測定 s3_client = boto3.client('s3', region) contents = [] next_token = '' while True: if next_token == '': response = s3_client.list_objects_v2(Bucket=bucket, Prefix=prefix) else: response = s3_client.list_objects_v2(Bucket=bucket, Prefix=prefix, ContinuationToken=next_token) contents.extend(response['Contents']) if 'NextContinuationToken' in response: next_token = response['NextContinuationToken'] else: break [print(r["Key"]) for r in contents]環境
サーバ等
- 基本的にCloud9 on EC2(t2.micro)で実行。
ビルド・デプロイ等
- 環境を汚したくない&面倒なので、全部Dockerで構築。
$ docker-compose up -d --build
- ちなみに構築資材は下記を参照。
DockerfileFROM golang:1.13.5-stretch as build RUN go get \ github.com/aws/aws-sdk-go/aws \ github.com/aws/aws-sdk-go/aws/session \ github.com/aws/aws-sdk-go/service/s3 COPY . /work WORKDIR /work RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main main.go FROM python:3.7.6-stretch as release RUN pip install boto3 COPY --from=build /work/main /usr/local/bin/main COPY --from=build /work/main.py /usr/local/bin/main.py WORKDIR /usr/local/bin/docker-compose.ymlversion: '3' services: app: build: context: . container_name: "app" tty: True environment: BUCKET: <Bucket> PREFIX: test/ REGION: ap-northeast-1S3バケット
東京リージョンにバケットを一つ作って、以下のツールで1000件程度作成。
#/bin/bash Bucket=<Bucket> Prefix="test" # テストファイル作成 dd if=/dev/zero of=testobj bs=1 count=30 # マスタファイルのコピー aws s3 cp testobj s3://${Bucket}/${Prefix}/testobj # マスタファイルを複製 for i in $(seq 0 9); do for k in $(seq 0 99); do aws s3 cp s3://${Bucket}/${Prefix}/testobj s3://${Bucket}/${Prefix}/${i}/${k}/${i}_${k}.obj done done測定
測定結果(1000 Object)
- Go
$ time docker-compose exec app ./main ~略~ real 0m21.888s user 0m0.580s sys 0m0.107s
- Python
$ time docker-compose exec app ./main.py ~略~ real 0m2.671s user 0m0.577s sys 0m0.104sGoがPythonより10倍遅い。なんでや!
Object数を増やしてみる
- もうすこしobjectを増やしてみましょう。とりあえず10000件あたりで。
#差分のみ for i in $(seq 0 99); do for k in $(seq 0 99); do
- ちなみにアップロード完了までに3、4時間かかりました。ツールはちゃんと作っとけばよかったね…
再測定結果(10000 Object)
- Go
$ time docker-compose exec app ./main ~略~ real 0m23.276s user 0m0.617s sys 0m0.128s
- Python
$ time docker-compose exec app ./main.py ~略~ real 0m5.973s user 0m0.576s sys 0m0.114s今回は4倍程度の差。
というよりObject数によらず18秒ほど差が出ている様子。うーむ。終わりに
- ライブラリの設定起因か、言語仕様の理解不足な気もしているので、もう少し情報を漁ってみたい。
- そもそもの目的であるGoroutineでの並列ダウンロード処理の効率が良ければ20秒程度は誤差な気もするので、残りも実装してみます。
気になるところ
- よく見るとuser, sysは同じ程度なのでS3でI/O周りが怪しい。
- goのコードを雑にprintデバッグしたところ("Start:", "End:")、list objectが処理時間の大半を占めている様子。もしやboto3とはS3設定のデフォルト値が異なるのだろうか。
- 同じコンテナで動かしてるので、T系インスタンスのCPUクレジット問題やNW帯域の差も関係ないと思うが……
- 前者はm5.largeに代えても解決しなかったので関係なさげ。
- 投稿日:2020-01-03T15:00:42+09:00
[Docker] laravelからmysql接続時にエラー 「php_network_getaddresses: getaddrinfo failed: Name or service not known」
DockerでLAMP環境を構築し、Laravelからmysqlに接続(php artisan migrate)しようとした際にエラーが発生。
つまづいたので、メモします。エラー内容
Illuminate\Database\QueryException : SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known (SQL: select * from information_schema.tables where table_schema = database and table_name = migrations and table_type = 'BASE TABLE')エラー内容を見たところ、mysqlに接続しているホスト名が違うらしいので、laravelの.envファイルとdocker-composer.ymlを確認。
.envDB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=database DB_USERNAME=hoge DB_PASSWORD=hogedocker-compose.ymlversion: '3' services: db: image: mysql:5.7 container_name: db-host environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: database MYSQL_USER: hoge MYSQL_PASSWORD: hoge別の方法でmysqlに接続
ホスト名は間違ってなさそうだと思い、データベースマネージャ(TablePlus)を使い接続を確認。
Ver: Mysql 5.x Host: 127.0.0.1 Port: 3306 User: hoge password: hoge Database: databaseTablePlusではつながりました。
もしや問題はDocker特有の何か、、??
DockerのDBコンテナ関連について調べた
こちらの記事によるとコンテナ内からのコンテナに接続する際はホスト名がIPでは無理らしく、service名で接続だそう
Laravel内の
.envDB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=database DB_USERNAME=hoge DB_PASSWORD=hogeを
.envDB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=database DB_USERNAME=hoge DB_PASSWORD=hogeに修正。
つながった
その他 参考記事
- 投稿日:2020-01-03T01:40:38+09:00
AWS FargateでSeleniumを使い定期的にチェックする環境を作ってみた
TL;DR (5行)
- 頻繁に手動で更新するようなWebページ(今回は例としてZOZOTOWNを使います)を自動チェックしたい
- Fargateを使ってSeleniumの実行環境を作ります
- ローカルのコンテナをECRにpushしてFargateにデプロイします
- Seleniumによるブラウザ操作をスケジュール設定し,バッチ処理として動作させます
- バッチ処理の結果は,CloudWatchにてチェック
注意
本記事はFargate+Selenium導入紹介を目的としています.
筆者は内定者で許可もとっているので,題材として自社サービスのZOZOTOWNを使ってます!
もし,記事内容を流用する場合はマナーや規約に違反しない範囲でお願いします!使用するサービスの説明
Fargateとは
通常コンテナをEC2で運用する場合,インスタンス管理する必要がありますが,Fargateの場合,インスタンス管理はAmazon側に任せ,コンテナを登録するだけでサーバレスにコンテナを動作させることができるサービスです.
サーバレスで有名なサービスとしてLambdaがありますが,こちらはコンテナを使えなかったり,タイムアウトなどの制約から柔軟性に欠ける部分があります.
一方で,Fargateはローカルで実行しているコンテナをそのまま登録して使えるため,多様なサービスの提供が可能です.
Seleniumとは
Webアプリのテストを自動化するためのブラウザ駆動型テストツールです.
PythonやRuby,Javaなど多様な言語に対応しており,簡単にテストスクリプトを作成することができます.
アーキテクチャ
今回は,AWS上に以下のようなアーキテクチャを構築します.
Dockerfileとメインコードの作成
Selenium + Pythonでテストスクリプトを作成します.
Dockerfileの作成
./DockerfileFROM joyzoursky/python-chromedriver:3.7-alpine3.8-selenium WORKDIR /usr/src ADD main.py /usr/src CMD ["python", "main.py"]今回,Selenium+Headless Chromeを使うにあたって,
ベースイメージはこちらを使っています.joyzoursky/python-chromedriver:3.7-alpine3.8-selenium
https://hub.docker.com/r/joyzoursky/python-chromedriver/メインコードの作成
./main.py# -*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.common.exceptions import TimeoutException, ElementClickInterceptedException, NoSuchElementException def check_coupon(driver, my_favorite_brand): # ZOZOのクーポンページに遷移 driver.get("https://zozo.jp/coupon/") i = 1 while True: try: coupon_brand = driver.find_element_by_xpath(f'//*[@id="body"]/div[3]/ul/li[{i}]/a/figure/div[2]').text if coupon_brand == my_favorite_brand: return True i += 1 except NoSuchElementException: return False if __name__ == '__main__': try: # Headless Chromeの設定 options = webdriver.ChromeOptions() options.add_argument('--no-sandbox') options.add_argument("--disable-setuid-sandbox") options.add_argument('--window-size=1420,1080') options.add_argument('--headless') options.add_argument('--disable-gpu') # Headless Chromeブラウザに接続 driver = webdriver.Chrome(options=options) # seleniumの動作タイムアウトを15秒間に設定 driver.implicitly_wait(15) # 好きなブランド my_favorite_brand = "Carlie e felice" # クーポンのチェック if check_coupon(driver, my_favorite_brand): print("見つけたよ! ", my_favorite_brand) else: print("今日は見つけられなかった・・・") # 例外処理 except ElementClickInterceptedException as ecie: print(f"exception!\n{ecie}") except TimeoutException as te: print(f"timeout!\n{te}") finally: # 終了 driver.close() driver.quit()クーポンページにブランド:Carlie e feliceがあるかどうかチェックします.
Requests + Beautiful Soup 4でスクレピングしても良かったのですが,今回はSeleniumを使った環境を構築したかったので,まさかり投げないでください;;
ローカル環境でコンテナの実行
# コンテナの構築 $ docker build -t zozo_check_coupons . # コンテナの実行 $ docker run -it --rm zozo_check_coupons 見つけたよ! Carlie e felice無事,ローカル環境で実行できたことを確認したら,次はこのコンテナをAmazon ECRにプッシュします.
ECRはAWS上のプライベートなDocker Hubみたいなイメージです.
AWSの必要環境の構築
ECRの環境を構築
ECRのリポジトリ作成
ECRに今回管理したいコンテナ専用のリポジトリを作成します.
このときの,リポジトリのURIはコンテナをプッシュするときに,使うのでメモしておきましょう.
ECRにログイン
$ aws ecr get-login --region ap-northeast-1 --no-include-email docker login -u AWS -p ... . . . .dkr.ecr.ap-northeast-1.amazonaws.com # 返ってきたdocker login ~をコピペして打ち込む $ docker login -u AWS -p ... Login SucceededLogin Succeededと表示されたらOKです
ECRにプッシュ
先程,メモしたリポジトリのURLをコピペし,作成したリポジトリにプッシュします
# リポジトリのURIでタグを付ける $ docker build -t xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/zozo_check_coupons . # タグをつけたコンテナをECRにプッシュする $ docker push xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/zozo_check_couponsイメージのURIは,タスク定義で使うので,メモしておきましょう
ECSでクラスター作成
コンテナを動作させる環境であるクラスターを作ります
ECSでタスクの定義
次に,タスクの定義をします.
タスク実行ロールが何もない場合は,下の余談を参照し,作成してください
余談 : CLIでタスク定義
- タスク実行に必要なロールを定義
./task-execution-assume-role.json{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "ecs-tasks.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
- 定義ファイルを用いて,ロールの作成
$ aws iam --region ap-northeast-1 create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://task-execution-assume-role.json
- タスクの定義ファイルを作成
/task-config.json{ "family": "zozo-check-coupons-task", "networkMode": "awsvpc", "containerDefinitions": [ { "name": "zozo-check-coupons-task", "image": "xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/zozo_check_coupons:latest", "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-region": "ap-northeast-1", "awslogs-group": "/ecs/zozo_check_coupons-task", "awslogs-stream-prefix": "ecs" } } } ], "requiresCompatibilities": ["FARGATE"], "cpu": "256", "memory": "512", "executionRoleArn": "arn:aws:iam::xxxxxxxx:role/ecsTaskExecutionRole" }
- 定義ファイルをもとにタスクを作成
$ aws ecs register-task-definition --cli-input-json file://task-config.jsonこれで,打ち間違い,漏れなくタスクを定義することができます
詳しくは,こちらを参照ください
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-cli-tutorial-fargate.htmlスケジュール実行の作成
次に,いよいよ定義したタスクをスケジュールで実行していきます.
- 作成したクラスターを選択し,タスクのスケジューリングを選択,そして作成を押します
CloudWatchでログをチェック
タスクが完了すると,CloudWatchの方にログが送られます
確認すると,以下のようなログがありました!
今日は無いみたいですね...
おわりに
Fargate + Seleniumの環境を作りました!
Fargateはコンテナを使って動かしたコンテナをそのまま登録できるので,かなり柔軟性はいいです.ですが,クローリングをする場合,CPUやメモリにページの読み込みが遅くなり,プログラムによるブラウザ操作がうまく行かなかったり,タイムアウトが発生してしまう場合があるので,sleepを入れる等の対策は十分にしたほうが良さそうです.
最後に,本記事は導入目的で紹介しているので,流用する場合はマナーや規約をよく読んでからお願いします!
参考文献
- 投稿日:2020-01-03T01:16:00+09:00
ASP.NET Core のWebアプリケーションを docker-compose で Dockerアプリケーション として構築する
概要
ASP.NET CoreのサンプルWebアプリケーションを題材として、docker-compose による Dockerアプリケーション の動作環境を構築する例を紹介します。
環境
- Windows10
- Visual Studio 2019
- ASP.NET Core 3.1
- Docker for Windows
サンプルアプリケーション
題材にしたサンプルアプリケーションです。
https://github.com/tYoshiyuki/dotnet-core-web-sample単純なToDoのWebアプリケーションです。トランザクションデータはデータベース (SQL Server) に保存しています。
これを Docker を利用して コンテナ化 してみましょう。システム構成
今回は、Docker for Windows を利用して、ローカルPC上にDocker環境を構築します。ローカル開発時は、IIS Express と LocalDB を利用して開発を行いましたが、これを変更します。フロントエンドは Nginx、データベースは SQL Express の Dockerイメージを利用し、アプリケーションのコンテナを含めて3つのコンテナで構築します。構成イメージは下記の通りです。
通常、ASP.NET Core アプリケーションを IIS でホストする場合には、ASP.NET Coreのミドルウェアにより、アプリケーションはIISと統合的に動作します。Nginxをリバースプロキシとしてフロントエンドに構築する場合は、ASP.NET Core アプリケーションは Kestrel で動作させておき、そこに対してHTTP通信を転送します。
Dockerfile
1. ASP.NET Core アプリケーション
まずは、ASP.NET Core アプリケーションをコンテナ化するために、Dockerfileを作成します。
Visual Studio > プロジェクト > 右クリック Dockerサポート > ターゲットOS Linuxから追加できる Dockerfile をベースにして編集を行います。DockerfileFROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base WORKDIR /app FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build WORKDIR /src COPY ["DotNetCoreWebSample.Web.csproj", "./"] RUN dotnet restore "DotNetCoreWebSample.Web.csproj" COPY . . WORKDIR "/src/." RUN dotnet build "DotNetCoreWebSample.Web.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "DotNetCoreWebSample.Web.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENV ASPNETCORE_URLS http://*:5000 ENTRYPOINT ["dotnet", "DotNetCoreWebSample.Web.dll"]Dockerfileの解説についてはここでは省略しますが、デフォルトでマルチステージビルドを行い、Dockerイメージサイズを削減するような設定になっています。ポイントとしては
[ENV ASPNETCORE_URLS http://*:5000]で、Kestrelが待ち受けを行うポート番号を指定している部分です。後々、Nginxでリクエストを転送する際における、送信先ポート番号になります。また、ソースコードも公式ドキュメントに従い、若干ですが変更を行います。
https://docs.microsoft.com/ja-jp/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1Startup.cspublic void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // ・・・一部省略・・・ app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); // ・・・一部省略・・・リバースプロキシを経由した際における、X-Forwarded-For・X-Forwarded-Protoヘッダの転送を行うようにします。
これは、IIS上でASP.NET Coreアプリケーションを動作させた場合は、既定で有効になっているので注意が必要です。公式ドキュメントにも記載があるため、目を通しておくことをお勧めします。
https://docs.microsoft.com/ja-jp/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-3.12. Nginx
次にNginx用の設定を作成します。
DockerfileFROM nginx:latest ENV ENTRYKIT_VERSION 0.4.0 RUN apt-get update && apt-get install -y wget \ && wget https://github.com/progrium/entrykit/releases/download/v${ENTRYKIT_VERSION}/entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \ && tar -xvzf entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \ && rm entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \ && mv entrykit /usr/local/bin/ \ && entrykit --symlink COPY ./nginx.conf.tmpl /etc/nginx/nginx.conf.tmpl ENTRYPOINT ["render", "/etc/nginx/nginx.conf", "--"] CMD [ "nginx", "-g", "daemon off;" ]nginx.conf.tmplworker_processes 1; events { worker_connections 1024; } http { sendfile on; upstream web-app { server {{ var "BACKEND_HOST" | default "localhost:5000" }}; } server { listen 80; server_name $hostname; location / { proxy_pass http://web-app; proxy_redirect off; proxy_http_version 1.1; proxy_cache_bypass $http_upgrade; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection keep-alive; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $server_name; } } }ポイントとしてはEntrykitを利用して、アプリケーションサーバの宛先 (BACKEND_HOST) を外部注入可能にしておきます。これに関しては、後ほど docker-compose.yml で解説を行います。
3. SQL Server Express
最後に SQL Server Express です。サンプルアプリケーションの機能としてはLocalDBで十分なのですが、公式にDockerイメージが存在しないようなので、SQL Server Expressを利用します。尚、実際にはDBデータを永続化する設定が必要ですが、今回は省略しています。
DockerfileFROM mcr.microsoft.com/mssql/server:2017-latest-ubuntudocker-compose.yml
作成した各コンテナを docker-compose を利用して起動してみましょう。
docker-compose.ymlversion: '3.4' services: app: build: context: ./DotNetCoreWebSample.Web dockerfile: Dockerfile environment: ConnectionStrings__DefaultConnection: "Server=sqlexpress;Database=master;User ID=sa;Password=P@ssw0rd;initial catalog=dotnetcorewebsample;MultipleActiveResultSets=True;App=EntityFramework;" expose: - 5000 depends_on: - sqlexpress sqlexpress: build: context: ./docker/sqlexpress dockerfile: Dockerfile environment: MSSQL_PID: "Express" ACCEPT_EULA: "Y" SA_PASSWORD: "P@ssw0rd" ports: - 1433:1433 web: build: context: ./docker/nginx environment: BACKEND_HOST: "app:5000" ports: - 80:80記載が長いですが、何点かポイントを解説します。
まず、
ConnectionStrings__DefaultConnection: "Server=sqlexpress;Database=master;User ID=sa;Password=P@ssw0rd;initial catalog=dotnetcorewebsample;MultipleActiveResultSets=True;App=EntityFramework;"の部分は、SQL Server Express への接続先情報を設定しています。コンテナ起動時に appsettings.json で設定している内容を上書きします。ネストされたJSONの要素 (ConnectionStrings > DefaultConnection) を表現する場合に、アンダーバー2つ (__) を使用します。
BACKEND_HOST: "app:5000"の部分で、ASP.NET Core アプリケーションへの送信先を設定しています。docker-composeでは、サービス名で各コンテナの宛先を解決出来るため、上記のような設定になります。docker-composeコマンドを実行し、各コンテナを起動します。
docker-compose up -d実行後
http://localhostでアクセスし、動作を確認します。まとめ
docker-composeを用いて、Dockerアプリケーションを構築する例を紹介させていただきました。
クロスプラットフォームを特徴とする .NET Core なので、Dockerを用いた開発も盛り上がると良いなと思います。ASP.NET Core と Azure で開発する場合、Web Apps や SQL Database といった優れた PaaS を利用することで、手軽にスケーラブルなアプリケーションを構築することが出来ます。そのため、Docker のようなコンテナ技術を利用するシーンは、あまり多く無いかも知れません。
ですが、ASP.NET Coreのアプリケーションをコンテナ化することで、AWS や GCP といった別クラウドサービスへの転用や、Kubernetesに代表される コンテナ オーケストレーション の恩恵を受けることが出来るようになります。システムアーキテクチャの選択肢として、考慮する価値は十分にあるのではないのでしょうか。
- 投稿日:2020-01-03T01:02:03+09:00
System Eventsでエラーが起きました: Docker Quickstart Terminalにはキー操作の送信は許可されません。(1002)
はじめに
こんなことあったよ!
根本的対策ではないけど一応投稿しようといったものです。
前回一度でも正常にDockerを起動したことがある方が対象になると思います。
最終的に使用するものはVirtualBoxです。
DockerでVirtualBoxを使っている方が対象です。
一応macですが今回に関してほぼ関係ないかと、、、あと…
Docker自体の記事も書いているのでもしよかったらみてください。
https://qiita.com/sachiko-kame/items/35e0cf07d117c3b92613事象
『久々にDocker触れてみようかな。まずはDockerフォルダのDocker Quickstart Terminalをクリック』
ターミナルが出たら、、次はコマンド打つんだよな〜うふふふふ、、、え?
System Eventsでエラーが起きました: Docker Quickstart Terminalにはキー操作の送信は許可されません。 System Eventsでエラーが起きました: Docker Quickstart Terminalにはキー操作の送信は許可されません。(1002)とりあえず検索以下URLヒット!
あ〜許可されていなかっただけか、、じゃ許可と!
https://forums.docker.com/t/error-trying-to-start-docker-quickstart-terminal/67623やりましたよ!証拠画像(こういうのをエビデンスというのですよね←知ったか)
再度クリック!、、、え同じエラー〜〜〜〜
エラーをなおしたいのではないDockerを使いたいんだ!←は?
強行突破
VirtualBoxから開いてみよう!!停止を実行に、、、(実行は写真には写っていない右上のボタン設定の隣の隣のところ)
※実行して処理が終わるまで待ってください
通常のターミナルを起動してと、
$ docker-machine start default
動いた、動いた。
あとは立て続けに$ docker-machine env default $ eval "$(docker-machine env default)" $ docker run hello-world
動いてるな
私はこう思った
どっちかでしか開けない? ←は?
キー操作の許可はってことはキーでクリックがダメってことでしょ!(。・ω・。) ←お?
だからあっているんだ! ←ま、そういうことにしといてやるか!





























