dockerでnginxを使用する際に"daemon off"することの意味
dockerでもnginxを使うことが多々あるでしょう。
ネットの記事や公式のDockerfileを見ると、以下のようなコマンドで実行しています。
CMD ["nginx", "-g", "daemon off;"]
この記事では上記のコマンドにはどんな意味があり、なぜそうする必要があるのかを書きます。
1. コマンドの意味
dockerを使わずにローカルで試す場合は以下のコマンドになります。
nginx -g "daemon off;"
gオプションおよび"daemon off;"についてはそれぞれ以下の公式の記載が参考になります。
- gオプション: Command-line parameters
- "daemon off;": Core functionality
gオプションはグローバルなディレクティブ(nginxにおける設定項目)を設定するためにつけます。
"daemon off;"はディレクティブ(ディレクティブは;で終わったり、{}を使って定義する)であり、
"daemon off;"の場合は nginxがdaemonとして起動しないようにする。
端的に説明すると、"daemon on;"とするとバックグラウンドで起動し、"daemon off;"とするとフォアグラウンドで起動する(デフォルトでは"daemon on;")。
試しにnginx -g "daemon off;"
とnginx -g "daemon on;"
をそれぞれ実行してみるとその差がよくわかるだろう。
2. なぜ"daemon off;"にするのか
結論からいうとそうしないとルート・プロセス終了し、コンテナが停止してしまうからです。公式にも解説があります。
試しに以下のコマンドでコンテナでプロセスを実行してみましょう。
docker run -d -p 80:80 nginx nginx
docker run -d -p 80:80 nginx nginx -g "daemon on;"
docker run -d -p 80:80 nginx
docker run -d -p 80:80 nginx nginx -g "daemon off;"
1, 2を実行した場合は以下のようにコンテナが停止してしまっている。
$ docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 00773f23396f nginx "nginx -g 'daemon on…" 2 seconds ago Exited (0) 1 second ago lucid_austin edda344f8191 nginx "nginx" 17 seconds ago Exited (0) 16 seconds ago eager_rubin
3, 4を実行した場合はともにコンテナが起動したままになる。
$ docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f1a77cf7bed7 nginx "nginx -g 'daemon of…" 5 seconds ago Up 3 seconds 0.0.0.0:80->80/tcp elastic_dijkstra
3の場合はDockerfileのCMDが実行されるため4と同じ結果になる。
2. Rust でHllo World -- 初めてのパッケージ作成 --
RustをインストールしたのでおなじみのHello Worldプログラムを作って見ましょう。
常々言っていますがまずは公式の情報を見るようにしましょう。リンクは以下です。
Get started - Rust programming language
こちらも以下に手順を書きます。
1. プロジェクトの作成
適当なディレクトリで新規のプロジェクトを作成します。
$ cargo new hello-rust Created binary (application) `hello-rust` package
cargo new
にも色々オプションがありますのでこちらを見ると良いでしょう。
new - The Cargo Book
実行すると以下のような構成のファイルが自動生成されます。
$ tree -a . -L 3 . └── hello-rust ├── .git │ ├── HEAD │ ├── config │ ├── description │ ├── hooks │ ├── info │ ├── objects │ └── refs ├── .gitignore ├── Cargo.toml └── src └── main.rs
.git
ディレクトリや.gitignore
についてはご存知かと思いますので割愛します。
Cargo.toml
ファイルは以下のような内容が自動生成されます。このファイルにはプロジェクトに関する情報や依存関係について記載します。
[package] name = "hello-rust" version = "0.1.0" authors = ["XXXXXX <XXXXXX@XXX.XXX>"] edition = "2018" [dependencies]
src/main.rs
にはアプリケーションのコードを書きます。初期生成時は以下のようになっています。
今回はそのまま使います。
fn main() { println!("Hello, world!"); }
2. 実行
試しに実行して見ましょう。RustにもGoのgo run
のようなコマンドがあるのでそれをプロジェクトのディレクトリ内で実行します。
$ cargo run Compiling hello-rust v0.1.0 (<プロジェクトのディレクトリ>) Finished dev [unoptimized + debuginfo] target(s) in 4.04s Running `target/debug/hello-rust src/main.rs` Hello, world!
上記のようにプログラムの実行とtargetディレクトリ作成が行われていることがわかります。 compileは初期実行時に行われ、以降ファイルが更新されるまでは行われません。
$ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.15s Running `target/debug/hello-rust` Hello, world!
3. ビルド
ビルド単独で実行することもできます。
こちらも色々オプションがありますのでこちらを見ると良いでしょう。
build - The Cargo Book
$ cargo build Compiling hello-rust v0.1.0 (<プロジェクトのディレクトリ>) Finished dev [unoptimized + debuginfo] target(s) in 0.56s
ビルドされるとtarget/debug
ディレクトリにhello-rust
が作成されるので実行して見ましょう。
$ ./target/debug/hello-rust Hello, world!
1. Rust と各種インストール(Rustupなど)
まずはRustをインストールします。
常々言っていますがまずは公式の情報を見るようにしましょう。リンクは以下です。
Get started - Rust programming language
一応説明込みで以下に手順を書きます。
Rustのインストールは公式サイトにもある通りRustupを使用することが推奨されています。
以下のコマンドでRustupをダウンロードします。
$ curl https://sh.rustup.rs -sSf | sh
rustc
,cargo
,rustup
が格納されている場所(~/.cargo/bin)までのパスは
Rustupのインストール中に自動的に.profile
,.bash_profile
に以下のように書き込まれます。
export PATH="$HOME/.cargo/bin:$PATH"
Rustupのアップデートはrustup update
でできます。
すぐに各種コマンドを実行したい場合はインストール中に表示される通り以下のコマンドを実行しましょう。
source $HOME/.cargo/env
中身は.profile
,.bash_profile
に追加された内容と同じです。
$ cat .cargo/env export PATH="$HOME/.cargo/bin:$PATH"
最後にインストールされていることとバージョンを合わせて確認します。
$ rustup --version rustup 1.18.2 (a0bf3c9cb 2019-05-02) $ rustc --version rustc 1.34.1 (fc50f328b 2019-04-24) $ cargo --version cargo 1.34.0 (6789d8a0a 2019-04-01)
Rust入門記
周りの人がおすすめしているのでやってみるかということでRustに入門することにしました。 今回はmac(mac os: 10.14.4)で入門していきます。
以下には今後書いていく記事のリンクを追加していきます。
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の設定が割と分かり難かったかなという印象です。皆さんもぜひ業務で役立ててみてください。
Google Cloud SDK コマンド覚え書き
GCPの勉強を行う上で、やはり業務を行う場合はCUIでの作業にも慣れないといかん。。。
というわけでGoogle Cloud SDKのコマンドをここに記す(gcloudのバージョン: Google Cloud SDK 232.0.0)。
公式情報: https://cloud.google.com/sdk/gcloud
Google Cloud SDK の取得
使用PCがmacのため後述のリンクを参照
Quickstart for macOS | Cloud SDK Documentation | Google Cloud
SDKの初期化
https://cloud.google.com/sdk/docs/quickstart-macos#initialize_the_sdk
プロジェクト
https://cloud.google.com/sdk/gcloud/reference/projects/
プロジェクトの作成
gcloud projects create <PROJECT_ID>
プロジェクトの一覧
gcloud projects list
プロジェクトの詳細
gcloud projects describe <PROJECT_ID >
設定
プロジェクトの設定
gcloud config set project <PROJECT_ID >
Typesctipt とVueで開発していたら,vue-routerの部分でtslintで「〜の引数を型'RouterOptions'のパラメーターに割り当てることはできません。」と出た時の対処法
vue cli3で簡単にTypescriptを導入できるようになったので開発していたところ、以下のようなエラーが出た。
[ts] 型 '{ mode: "history"; base: any; routes: ({ path: string; component: VueConstructor<Vue>; } | { path: string; components: VueConstructor<Vue>; } | { path: string; redirect: string; })[]; }' の引数を型 'RouterOptions' のパラメーターに割り当てることはできません。 プロパティ 'routes' の型に互換性がありません。 型 '({ path: string; component: VueConstructor<Vue>; } | { path: string; components: VueConstructor<Vue>; } | { path: string; redirect: string; })[]' を型 'RouteConfig[]' に割り当てることはできません。 型 '{ path: string; component: VueConstructor<Vue>; } | { path: string; components: VueConstructor<Vue>; } | { path: string; redirect: string; }' を型 'RouteConfig' に割り当てることはできません。 型 '{ path: string; components: VueConstructor<Vue>; }' を型 'RouteConfig' に割り当てることはできません。 プロパティ 'components' の型に互換性がありません。 型 'VueConstructor<Vue>' を型 'Dictionary<Component>' に割り当てることはできません。 型 'VueConstructor<Vue>' のインデックス シグネチャがありません。 (property) RouterOptions.mode?: "hash" | "history" | "abstract" | undefined
vue-router部分の実装はこう。routes.tsでルーティングを定義し、index.tsでRouterとしてexportする。
今回のエラーはindex.ts で出ました。
index.ts
import Vue from 'vue'; import Router, { RouterOptions } from 'vue-router'; import routes from './routes'; Vue.use(Router); export default new Router({ mode: 'history', base: process.env.BASE_URL, routes, });
routes.ts
import TodoList from '@/components/templates/TodoList.vue'; import TodoListDetail from '@/components/templates/TodoListDetail.vue'; export default [ { path: '/tasks', component: TodoList, }, { path: '/tasks/:id', components: TodoListDetail, }, { path: '*', redirect: '/tasks', }, ];
基本的には以下のリンクを見ればわかります。
この場合は型アサーションをする必要があり、修正方法は以下の2つです。
- index.tsを修正(RouterOptionsにする)
import Vue from 'vue'; import Router, { RouterOptions } from 'vue-router'; import routes from './routes'; Vue.use(Router); export default new Router({ mode: 'history', base: process.env.BASE_URL, routes, } as RouterOptions);
- routes.tsを修正(RouteConfig[]にする)
import TodoList from '@/components/templates/TodoList.vue'; import TodoListDetail from '@/components/templates/TodoListDetail.vue'; import { RouteConfig } from 'vue-router'; export default [ { path: '/tasks', component: TodoList, }, { path: '/tasks/:id', components: TodoListDetail, }, { path: '*', redirect: '/tasks', }, ] as RouteConfig[];
以上、ご参考になれば幸いです。