- 投稿日:2020-10-27T19:47:45+09:00
datadogでdocker-composeを使ってnginxを監視する方法
Datadogでnginxを監視する
有償の監視ツールdatadogでnginxを監視する方法。
ただし、datadogのagentはdocker-composeでセットアップする場合・・公式ドキュメント(ほぼ役に立たない)
https://docs.datadoghq.com/ja/integrations/nginx/?tab=hostまず、これを見てnginxのstatus_moduleを入れてください。
(ここまではdocker関係ないです)要は、localhost:81でステータスが見れてたらOK。
公式ドキュメント
docker-composeを使ってnginxを監視する設定ぐらいサンプルがあるやろ!!!
コンテナ環境の場合は、オートディスカバリーのインテグレーションテンプレートのガイドを参照して、次のパラメーターを適用してください。
で、案内されるページに行っても、docker-composeのサンプルもなにもない・・・
https://docs.datadoghq.com/ja/agent/kubernetes/integrations/?tab=kubernetes要は、適当にコンフィグファイル.yamlを作ってコピーするなり、マウントしてやればいいらしい?
サンプルファイル?なにそれ?conf.d/.d/conf.yaml
で、nginx用の設定はこれらしい
<インテグレーション名> nginx <初期コンフィギュレーション> 空白または {} <インスタンスコンフィギュレーション> {"nginx_status_url": "http://%%host%%:81/nginx_status/"}さらにわからん!!!!<インテグレーション名>って何を入れたらいいんですか?
どこに?何というファイル名で?
公式ドキュメントが不親切すぎる!!!!datadogは有償ツール故に試してみた的な記事も殆どない・・・
ということで、以下が正解のdocker-compose.ymlファイルです。
docker-compose.yml
version: "3.8" services: web: build: context: ./docker/nginx ports: - 80:80 # 関係ない設定は削除 # ここまでの設定はdatadogとは関係なし 81番ポートを開ける必要はなし # ここからがdatadogでログを取る核心部分の設定 links: - dd-agent:dd-agent depends_on: - dd-agent labels: com.datadoghq.ad.check_names: '["nginx"]' com.datadoghq.ad.init_configs: '[{}]' com.datadoghq.ad.instances: '[{"nginx_status_url": "http://%%host%%:81/nginx_status"}]' com.datadoghq.ad.logs: '[{"source": "nginx", "service": "web"}]' # datadogのコンテナ設定 dd-agent: container_name: dd-agent image: datadog/agent:7 environment: - DD_API_KEY=ここに自分のAPIキーを書く - DD_APM_ENABLED=true - DD_LOGS_ENABLED=true - DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true - DD_AC_EXCLUDE="name:dd-agent" volumes: - /var/run/docker.sock:/var/run/docker.sock - /proc/:/host/proc/:ro - /sys/fs/cgroup:/host/sys/fs/cgroup:ro ports: - "8126:8126/tcp"これでコンテナを立ち上げて、docker psで生存確認。healtyになっていたらOK。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 577f6b34b971 datadog/agent:7 "/init" 39 seconds ago Up 37 seconds (healthy) 8125/udp, 0.0.0.0:8126->8126/tcp dd-agent生きていれば、datadogのstatusチェック。
$ docker exec -it dd-agent agent statusこのコマンドで、checkの中にnginxって文字列があってなにかしているようであればOK。(長いので省略)
nginx (3.9.0) ------------- Instance ID: nginx:[OK] Configuration Source: docker:docker:// Total Runs: 4 Metric Samples: Last Run: 7, Total: 28 Events: Last Run: 0, Total: 0 Service Checks: Last Run: 1, Total: 4 Average Execution Time : 5ms Last Execution Date : 2020-10-27 10:20:20.000000 UTC Last Successful Execution Date : 2020-10-27 10:20:20.000000 UTC metadata: version.major: 1 version.minor: 18 version.patch: 0 version.raw: 1.18.0 version.scheme: semverこんな基本的なアプリケーションの組み合わせのサンプルも記事も無いとかdatadog無いわ・・・・厳しいわ・・・
ハマリポイント
API_KEYじゃなくてDD_API_KEY
古いdd-agentを使っているとstatusコマンドが存在しなかった etc多少参考になった記事
https://y-ohgi.com/2019-aws-handson/datadog/docker-compose/
https://tech.griphone.co.jp/2018/12/02/advent-calendar-20181202/
https://qiita.com/comefigo/items/4d867a39ad2fd5b9bbd2
https://qiita.com/spesnova/items/b1f2cc4e33ddf7cea285
- 投稿日:2020-10-27T18:35:07+09:00
【GCP】ローカルのDockerイメージをContainer RegistryにPushするまで
概要
ローカル環境で開発してビルドしたコンテナイメージを、ローカルから「Container Registry」のリポジトリにプッシュするための作業
参考
https://cloud.google.com/container-registry/docs/pushing-and-pulling#push_the_tagged_image_to
手順
1. gcloudの設定
- gcloudコマンドをローカル環境にインストール
- 初期設定
gcloud init
2. イメージのPush/Pull用サービスアカウント作成
自分のユーザーアカウントを使う場合、プロジェクトがいろいろと紐づいているとプロジェクトIDの選択ミスが怖いので、専用のサービスアカウントを作る。
- サービスアカウント作成
- コンソールで作業
- 権限設定
- 「Container Registry」のコンテナイメージはCloud Storageで管理され、権限も、Cloud Storageの「ストレージ管理者」権限を付与するだけ。
- https://cloud.google.com/container-registry/docs/access-control#grant https://cloud.google.com/sdk/docs/authorizing?hl=ja#authorizing_with_a_service_account
- サービスアカウントのキーを作成し、ローカルで認証設定
gcloud auth activate-service-account
- https://cloud.google.com/sdk/docs/authorizing?hl=ja#authorizing_with_a_service_account
3. Docker 認証設定
gcloud をDockerの認証ヘルパーとして使用するための設定
- ローカルで
gcloud auth configure-docker
を実行4. Dockerイメージのプッシュ
※ もし複数アカウントがある場合は以下でアカウントを切り替える
gcloud config set account [ACCOUNT]
- ローカル イメージにレジストリ名でタグ付けする
- 命名規則 : [HOSTNAME]/[PROJECT-ID]/[IMAGE]
- [HOSTNAME] : 以下から選ぶ。これでイメージを保存する場所が決まる。
- gcr.io は米国内のデータセンターでイメージをホストしていますが、今後は場所が変更される可能性があります。
- us.gcr.io は米国内のデータセンターでイメージをホストしていますが、gcr.io によってホストされるイメージからは独立したストレージ バケットです。
- eu.gcr.io は、欧州連合でイメージをホストします。
- asia.gcr.io は、アジアのデータセンターでイメージをホストします。
- [PROJECT-ID] : 対象のGoogle CloudプロジェクトのプロジェクトID
- [IMAGE] : コンテナイメージの名前
- タグ付けコマンド :
docker tag [ローカル イメージ名またはイメージ ID] [レジストリ名]:[タグ(未指定はlatest)]
- プッシュ
docker push [レジストリ名]:[タグ(未指定はlatest)]
新規でプッシュすると、Container Registry上にリポジトリができる。
- 投稿日:2020-10-27T17:40:27+09:00
プロキシ環境下の Docker
Docker おじさんです。
今回は
「顧客の本番環境がプロキシを通さないとインターネットに出れないことが判明した!!!」
という状況で焦らないためのメモ。Docker のインストール
Debian / Ubuntu 前提で。
プロキシ環境下なので以下は普通に通らないと思うが、
~/.bashrc
とかで環境変数http_proxy
などを設定してもsudo
すると環境変数は引き継がれないのでそのままでは通らない。$ sudo apt-get install docker.io
sudo
に-E
オプションを付ければ環境変数を引き継げば通るが毎回-E
をつけるのが面倒なので、別の方法として apt の設定ファイルを書いてしまったほうが楽。/etc/apt/apt.conf.d/00-proxyAcquire::http::Proxy "http://{HOST}:{port}"; Acquire::https::Proxy "http://{HOST}:{port}";RHEL / CentOS の人は yum 用の設定方法があると思うので適当にググってやっていって欲しい。
Docker Engine
docker pull
などでイメージを落としてくる場合は Docker Engine にプロキシ設定をする必要がある。単純に環境変数
HTTP_PROXY
HTTPS_PROXY
を設定すればいいのだが、最近は Systemd で動いていることがほとんどだと思うので Systemd の設定ファイルで環境変数を指定するのが手っ取り早い。/lib/systemd/system/docker.service[Service] Environment=HTTP_PROXY=http://{HOST}:{port} Environment=HTTPS_PROXY=http://{HOST}:{port}Docker イメージのビルド時
Docker イメージのビルド時に限らないが、
apt-get install
などでインターネットに出たい場合は、そのツールひとつひとつにプロキシ設定をする必要がある。apt-get や pip などは環境変数を設定するだけでプロキシを通ってくれるので、とりあえず環境変数を設定しておき、個別に対応が必要なツールについては個別に対応していく、となる。ビルド時に環境変数を設定するには Dockerfile に環境変数を指定してもいいが、ARG を使うのがよさそう。
例えば Docker Compose の設定ファイルで args を指定する場合は、サービスの build オプションを以下のように指定する。
docker-compose.ymlbuild: context: . args: - http_proxy=http://{HOST}:{port} - https_proxy=http://{HOST}:{port} - HTTP_PROXY=http://{HOST}:{port} - HTTPS_PROXY=http://{HOST}:{port}ツールによって対応している環境変数名が大文字だったり小文字だったりするので、両方指定しておいたほうが良い。
(例えば apt-get は大文字のHTTP_PROXY
を指定しても認識してくれない)Docker コンテナ起動時
コンテナ起動時はビルド時と同様にツールひとつひとつにプロキシ設定をする必要があるため、個別対応以外で出来ることといえば環境変数を設定するだけとなる。
コンテナ起動時に毎回環境変数を指定するのは手間なので、
~/.docker/config.json
を書いておくとコンテナ内にHTTP_PROXY
などを自動で設定してくれる機能を使うと楽。~/.docker/config.json{ "proxies": { "default": { "httpProxy": "http://{HOST}:{port}", "httpsProxy": "http://{HOST}:{port}" } } }Configure Docker to use a proxy server | Docker Documentation
その他
Docker 以外の設定で環境変数では対応できないやつ (git とか curl とか boto3 とか) そのへんはググって個別によしなに設定する。
- 投稿日:2020-10-27T14:55:54+09:00
Dockerのpython:x.x.x-alpine imageでdjangoアプリを立ち上げmigrateしたときに"Cannot use ImageField because Pillow is not installed"エラーが出る問題
DjangoアプリをDockerに乗せて本番環境にデプロイするときに生じた問題です。
DjangoではImageファイルを扱う際にPillowというライブラリを使うのですが、このライブラリが厄介で、エラーを起こしやすいです。
次のDockerfileを使ってbuildします。Dockerfile########### # BUILDER # ########### # pull official base image FROM python:3.7.3-alpine as builder # set work directory WORKDIR /usr/src/app # set environment variables #ENV PATH="/scripts:${PATH}" ENV PYTHONUNBUFFERD 1 ENV PYTHONDONTWRITEBYTECODE 1 # install psycopg2 dependencies RUN apk add --update --no-cache --virtual .tmp-build-deps postgresql-client jpeg-dev \ .tmp-build-deps gcc build-base python3-dev musl-dev linux-headers \ postgresql-dev RUN apk add --update --no-cache --virtual .build-deps build-base python3-dev musl-dev \ libc-dev linux-headers postgresql-dev musl-dev zlib zlib-dev gettext \ postgresql-client gettext-dev libjpeg-turbo pcre RUN apk add --update libxml2-dev libxslt-dev libffi-dev gcc libgcc openssl-dev curl RUN apk add --update jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev libjpeg RUN apk add --no-cache jpeg # lint RUN pip install --upgrade pip RUN pip install --upgrade setuptools RUN pip install flake8 RUN pip install pillow COPY . . RUN flake8 --ignore=E501,F401 . # install dependencies COPY ./requirements.txt . RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt RUN apk del .tmp-build-deps ######### # FINAL # ######### # pull official base image FROM python:3.7.3-alpine # create directory for the app user RUN mkdir -p /home/app # create the app user RUN addgroup -S app && adduser -S app -G app COPY --from=builder /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.7/site-packages # create the appropriate directories ENV HOME=/home/app ENV APP_HOME=/home/app/web RUN mkdir $APP_HOME #RUN mkdir $APP_HOME/staticfiles #RUN mkdir $APP_HOME/mediafiles WORKDIR $APP_HOME # install dependencies RUN apk update && apk add libpq COPY --from=builder /usr/src/app/wheels /wheels COPY --from=builder /usr/src/app/requirements.txt . RUN pip install --no-cache /wheels/* #RUN pip install pillow # copy entrypoint-prod.sh COPY ./entrypoint.prod.sh $APP_HOME # copy project COPY . $APP_HOME # chown all the files to the app user RUN chown -R app:app $APP_HOME # change to the app user USER app #RUN chmod +x /home/app/web/entrypoint.prod.sh # run entrypoint.prod.sh ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]:docker-compose.ymlは次のようにします。
docker-compose.ymlversion: '3.7' services: web: build: context: ./app dockerfile: Dockerfile command: gunicorn backend.wsgi:application --bind 0.0.0.0:8000 ports: - 8000:8000 env_file: - ./.env.dev depends_on: - db db: image: postgres:12.0-alpine volumes: - postgres_data:/var/lib/postgresql/data/ environment: - POSTGRES_USER=hello_django - POSTGRES_PASSWORD=hello_django - POSTGRES_DB=hello_django_dev - POSTGRES_HOST_AUTH_METHOD=trust nginx: build: ./nginx ports: - 1337:80 depends_on: - web volumes: postgres_data:このように書いてdocker-compose up -d buildして、
docker-compose exec web python manage.py migrateすると、
記事タイトルのように"Cannot use ImageField because Pillow is not installed"エラーが起こります。
エラー文に従ってdocker-compose exec web python -m pip install Pillowしてみます。
というか、docker-compose exec web python -m pip listでライブラリを見ると、Pillowは無事インストールされています。
なぜだ......調べるとこのエラーはよく起こるようで、pip install -m Pillowをしろだとか、alpineにapkで色々jpeg-devとかのdependenciesを入れろだとか、pythonとpillowのversionを変えろとか出てきます。色々試してみましたが、どうやら、alpineイメージではPillowを扱うことができないようです。
Dockerイメージをpython-x.x.x-alpineからpython-x.x-busterに変更して色々dependenciesを入れてbuildしたところ、無事migrateできました。解決法としてはシンプルです。django on docker(alpine)でPillowは使えません。以上です。
- 投稿日:2020-10-27T13:50:12+09:00
Dockerコンテナ内でcomposer updateしようとしたらproc_open(): fork failed と怒られた
環境
Docker for windowsを使用しています.
Docker Machineのバージョンは以下の通りです.docker-machine.exe version 0.16.1, build cce350d7Docker内でcomposer updateしようとした
LaravelをDockerコンテナ内で動かしているのですが,
composer update
をしようとしたら怒れてしましました.PHP Fatal error: Uncaught exception 'ErrorException' with message 'proc_open(): fork failed - Cannot allocate memory'どうやらメモリ領域が足りないことが原因で起きたようです.
そこでスワップ領域を拡張しようと思い,以下のコマンドを実行したのですが,swapon failed: Operation not permitted
と怒られました./bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024 /sbin/mkswap /var/swap.1 /sbin/swapon /var/swap.1権限を与えてもダメでした.
解決方法
Docker Machineのメモリを増やしたらうまくいきました.
Docker Machineを一度停止し,Oracle VM VirtualBox マネージャーを起動します.
以下のように該当するMachineの設定を開き,システム>マザーボード>メインメモリでメモリを増やします.
自分の環境では2GBでうまくいきました.
- 投稿日:2020-10-27T02:01:02+09:00
ApolloサーバーとPrismaを使用したJWT認証
はじめに
本記事ではGraphQLを利用したユーザー認証についてテストを行った備忘録となります。
認証にはJWTとBcryptを利用しており、Prismaを使用するApolloサーバーにてテストをしました。Prismaとは?
GraphQLサーバー(本記事ではGraphQLサーバーとしてApolloを利用)とデータベースを繋ぐORMの一つ。
噛み砕いて言うならば、スキーマ定義をしたQueryやMutationに応じたデータをデータベースから持ってきてくれるツールみたいなイメージです。ORMとは下記の機能のまとまりのことを指します。
- データベースからデータを取得する
- 取得したデータをオブジェクト化する
- データの更新・変更などをデータベースに格納する
JWTとは?
JWT(ジョット)とはJSON Web Token の略で、JSONデータに署名や暗号化を施す方法のことを指します。
本記事ではログイン認証に利用します。
詳しくはこちらPrismaの設定
早速Prismaの設定からスタートしていきます?
$ mkdir jwt-Auth $ cd jwt-Auth $ npm init $ npm install apollo-server graphql prisma-client-lib $ npm install -g prismaプロジェクト作成後に、npm installが完了したら、
ORMとしてPrismaを使用するようにアプリケーションを設定します。$ prisma initそのままDockerを使い、Prismaの設定を行なっていきます。
? Set up a new Prisma server or deploy to an existing server? ❯ Create new database Set up a local database using Docker ? What kind of database do you want to deploy to? ❯ PostgreSQL PostgreSQL database ? Select the programming language for the generated Prisma client ❯ Prisma JavaScript Client成功すると下記のような案内が表示されます。
Created 3 new files: prisma.yml Prisma service definition datamodel.graphql GraphQL SDL-based datamodel (foundation for database) docker-compose.yml Docker configuration file Next steps: 1. Start your Prisma server: docker-compose up -d 2. Deploy your Prisma service: prisma deploy 3. Read more about Prisma server:Dockerコンテナの起動
Dockerコンテナを起動する前に、生成されたファイルの設定変更をします。
①docker-compose.yml内の中ほどある、portに関する設定のコメントアウトを外す。
こちらがコメントアウトされたままだと、localhostで立ち上げることが出来ません。docker-compose.yml# Uncomment the next two lines to connect to your your database from outside the Docker environment, e.g. using a database GUI like Postico ports: - "5432:5432"②datamodel.graphqlの書き換えをします。こちらのファイルがORMとして機能するために必要なファイルの元になります。
datamodel.graphqltype User { id: ID! @id name: String! email: String! @unique password: String! }③prisma.ymlは変更不要ですが、下記のようになります。
prisma.ymlendpoint: http://localhost:4466 datamodel: datamodel.prisma generate: - generator: javascript-client output: ./generated/prisma-client/準備ができたら、先ほどの「Next steps」の案内に従い、コンテナを起動させます。
$ docker-compose up -d $ prisma deploy $ prisma generate以上のコマンドを正常に実行すると、datamodel.prismaファイルから生成されたORMとして機能するために必要なファイルが作成されます。
下記のようにPrismaインスタンスをアプリケーションにインポートするだけで利用すると、ミューテーションやクエリを実行するときに、データベースを実際に操作できるようになります。
const { prisma } = require('./generated/prisma-client')Apolloサーバーに関するコードを書く
Prismaの設定が完了したら、GraphQlサーバーとして、Apolloを利用する準備をしていきます。bcryptとはパスワードのハッシュ化のために利用するライブラリです。
$ mkdir resolver $ touch index.js schema.js resolver/Mutation.js $ npm install bcrypt jsonwebtoken先ずはスキーマを書きます。
今回はサインアップとサインインを試すべく、それに当たるスキーマをMutation内で定義しています。schema.jsconst {gql} = require('apollo-server'); const typeDefs = gql` type Query { users(query: String): [User!]! } type Mutation { createUser(data: CreateUserInput!): AuthPayload! login(data: LoginUserInput!): AuthPayload! } type AuthPayload { token: String! user: User! } input CreateUserInput { name: String! email: String! password: String! } input LoginUserInput { email: String! password: String! } type User { id: ID! name: String! email: String password: String! } ` module.exports = typeDefs;JWTとbcryptはこちらで利用しています。
Prismaはすべてのリゾルバー間で共有するので、第三引数のcontextとして使います。Mutation.jsconst bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); const Mutation = { async createUser(parent, args, { prisma }, info) { const { data: { email, name, password } } = args; const newUser = await prisma.createUser({ email, name, // bcryptでパスワードをハッシュ化 password: bcrypt.hashSync(password, 3) }); // サーバーがJWTトークンを発行 return {token : jwt.sign(newUser, "supersecret")}; }, async login(parent, args, { prisma }, info) { const { data: { email, password } } = args; // メールアドレスと照合 const [ signInUser ] = await prisma.users({ where: { email } }) if (!signInUser) throw new Error('Unable to Login'); // パスワードと照合 const isMatch = bcrypt.compareSync(password, signInUser.password); if (!isMatch) throw new Error('Unable to Login'); // 認証済みのトークンが返ってくる return {token : jwt.sign(signInUser, "supersecret")}; }, } module.exports = Mutation最後にApolloサーバーを立ち上げする設定の処理を書きます。
index.jsconst { ApolloServer } = require('apollo-server'); const Mutation = require('./resolver/Mutation') const typeDefs = require('./schema') // datamodel.prismaファイルから生成されたPrismaインスタンス const { prisma } = require('./generated/prisma-client') const server = new ApolloServer({ typeDefs: typeDefs, resolvers: { Mutation }, context: { prisma } }) server.listen().then(({ url}) => { console.log(`? Server ready at ${url}`); });GraphQL IDEにてテストをする
GraphQL IDEを使ってテストをします。
$ node index.js ? Server ready at http://localhost:4000/サインアップ
IDE上でname,email.passwordを含むクエリを書きます。
JWTトークンが返ってきました。
サインイン
続いてサインインの確認です。
サインアップと同じ、email,passwordをクエリで書きます。サインアップの時と同一のJWTトークンが返ってきました!
成功です!おわりに
以上、GraphQLにおけるログイン認証をテストしてみました。
PrismaとDockerで素早く環境を作ることができ、その後はほとんど意識することなく、コードを書けたのはGraphQLの強みであるように感じました。それでは、また?