Dockerで構築したRails環境にDatadogを導入する
最近業務でDatadogを使うようになったので勉強がてら試してみようと思います。 バージョンは以下の通りです。
まずはAPIモードでプロジェクトを作りましょう(--api を付けるとAPIモードになる)。
$ rails new datadog-test --api --database=mysql
gemsetも作成しましょう。
$ rbenv gemset create 2.6.3 datadog-test $ echo > .rbenv-gemsets datadog-test
環境はDockerで作ります。mysqlも使いたいのでdocker-composeで合わせて作ります。 image軽量化のためにmulti stage buildにしています。
- Dockerfile
FROM ruby:2.6.3-alpine as builder RUN apk --update add --virtual build-dependencies \ build-base \ curl-dev \ mysql-dev \ linux-headers RUN gem install bundler WORKDIR /tmp COPY Gemfile Gemfile COPY Gemfile.lock Gemfile.lock ENV BUNDLE_JOBS=4 RUN bundle install RUN apk del build-dependencies FROM ruby:2.6.3-alpine ENV LANG ja_JP.UTF-8 RUN apk --update add \ bash \ mariadb-dev \ tzdata RUN gem install bundler WORKDIR /tmp COPY --from=builder /usr/local/bundle /usr/local/bundle ENV APP_HOME /myapp RUN mkdir -p $APP_HOME WORKDIR $APP_HOME COPY . $APP_HOME # Start the main process. CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]
- docker-compose.yml
version: '3' services: db: image: mysql:5.7 volumes: - mysql_data:/var/lib/mysql ports: - "3306:3306" restart: always environment: MYSQL_ROOT_PASSWORD: hi54ftyugiy3 api: build: . ports: - "3000:3000" depends_on: - db environment: MYSQL_PASSWORD: hi54ftyugiy3 volumes: mysql_data:
config/database.yml は自動生成されたものを一部修正しています。hostで指定する値はdocker-compose.yml のmysqlのservice名です。
- config/database.yml
default: &default adapter: mysql2 encoding: utf8 host: db pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: <%= ENV.fetch("MYSQL_PASSWORD") { "root" } %> socket: /tmp/mysql.sock development: <<: *default database: datadog-test_development # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: datadog-test_test
バックグラウンドでコンテナを起動します。
$ docker-compose up -d --build ・・・ ・・・ Successfully built 34aeb8dd5580 Successfully tagged datadog-test_api:latest Creating datadog-test_db_1 ... done Creating datadog-test_api_1 ... done
DBの作成を行います。
$ docker-compose run api bundle exec rails db:create Starting datadog-test_db_1 ... done Created database 'datadog-test_development' Created database 'datadog-test_test'
http://localhost:3000/ にアクセスしてRailsの起動を確認します。
次に適当なAPIを作成します。本筋ではないのでscaffoldで作ります。
bin/rails g scaffold Book title:string
titleだけだとかっこ悪いのでmigrationファイルをいじります。
- db/migrate/20190420163659_create_books.rb
class CreateBooks < ActiveRecord::Migration[5.2] def change create_table :books do |t| t.string :title t.string :author t.string :publisher t.text :isbn t.datetime :publication_date t.text :description t.timestamps end end end
許容するparameterも更新しておきます。
- app/controllers/books_controller.rb
・・・ ・・・ # Only allow a trusted parameter "white list" through. def book_params params.require(:book).permit( :title, :author, :publisher, :isbn, :publication_date, :description ) end
更新するためコンテナを起動し直します。
$ docker-compose up -d --build
DBの更新を適用します。
$ docker-compose run api bundle exec rails db:migrate RAILS_ENV=development Starting datadog-test_db_1 ... done == 20190420163659 CreateBooks: migrating ====================================== -- create_table(:books) -> 0.0161s == 20190420163659 CreateBooks: migrated (0.0163s) =============================
再度コンテナを起動し直します。
$ docker-compose up -d --build
適当にデータを登録してみましょう。
$ curl -X POST \ > http://localhost:3000/books \ > -H 'content-type: application/json' \ > -d '{ > "title": "桃太郎", > "author": "名無し", > "publisher": "名無し出版", > "isbn": "0000-0000", > "publication_date": "2018-04-20", > "description": "昔々あるところに" > }' {"id":5,"title":"桃太郎","author":"名無し","publisher":"名無し出版","isbn":"0000-0000","publication_date":"2018-04-20T00:00:00.000Z","description":"昔々あるところに","created_at":"2019-04-20T17:13:52.000Z","updated_at":"2019-04-20T17:13:52.000Z"}
登録結果を確認してみます(そのままだと見にくいのでjqコマンドで整形しています)。
$ curl -X GET http://localhost:3000/books | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 267 0 267 0 0 17248 0 --:--:-- --:--:-- --:--:-- 17800 [ { "id": 1, "title": "桃太郎", "author": "名無し", "publisher": "名無し出版", "isbn": "0000-0000", "publication_date": "2018-04-20T00:00:00.000Z", "description": "昔々あるところに", "created_at": "2019-04-20T17:13:52.000Z", "updated_at": "2019-04-20T17:13:52.000Z" } ]
それではDatadogを導入していきます。ここを参考にすると良いでしょう。 docs.datadoghq.com
まずはgemのddtraceを追加します。
- Gemfile
+ gem 'ddtrace'
docker-compose.ymlにDatadog用のコンテナを追加します。今回はログも取得したいので以下を参考にしましょう。
docs.datadoghq.com docs.datadoghq.com
- docker-compose.yml
version: '3' services: db: image: mysql:5.7 volumes: - mysql_data:/var/lib/mysql ports: - "3306:3306" restart: always environment: MYSQL_ROOT_PASSWORD: hi54ftyugiy3 api: build: . ports: - "3000:3000" depends_on: - db environment: MYSQL_PASSWORD: hi54ftyugiy3 + links: + - dd-agent + + dd-agent: + image: datadog/agent:latest + ports: + - 8126:8126 + environment: + DD_API_KEY: <DatadogのAPI KEY> + DD_APM_ENABLED: "true" + DD_LOGS_ENABLED: "true" + DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL: "true" + DD_AC_EXCLUDE: "name:datadog-agent" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - /proc/:/host/proc/:ro + - /sys/fs/cgroup/:/host/sys/fs/cgroup:ro volumes: mysql_data:
logを確認するため、Railsのログを出力させます。
- Dockerfile
# Start the main process. - CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"] + CMD bundle exec rails server -b 0.0.0.0 && tail -f log/development.log
initializerも作成します。
- config/initializers/datadog.rb
require 'ddtrace' Datadog.configure do |c| # This will activate auto-instrumentation for Rails c.use :rails c.tracer hostname: 'dd-agent', port: 8126 end
再度コンテナを起動し直します。
$ docker-compose up -d --build
適当なAPIを叩いて確認します。
ちゃんと捕捉できていますね。試しにわざと例外を発生されたりもしましたが、独自のrender用のメソッドを追加したりもしましたが、問題なくログを取得できました。
終わってみると簡単でしたが、Dockerの設定が割と分かり難かったかなという印象です。皆さんもぜひ業務で役立ててみてください。