20200220のdockerに関する記事は21件です。

Laravelでミニブログを作ろう #1

laravelの使い方を一通り習ったので、laravelを使って(競プロの勉強の合間に)ちょこちょこミニブログを作っていくことにします。
作成していく過程で最近学習したAWSだったりCircle CIだったりの復習をしていければと考えてます。
(果たして完成するまでに何ヶ月かかるのか)

要件定義

アプリの概要

Markdown記法で記事が書けるミニブログ

主要な機能

  • 記事の作成、編集、更新、削除、下書き(ユーザーは複数人登録できる)
  • 画像投稿
  • タグ付け機能(記事を作成したユーザー以外もタグ付けできる)
  • いいね機能
  • Markdownエディタ
  • レスポンシブデザイン
  • 管理人機能(ユーザー一覧、ユーザー詳細表示)

技術要件

  • フロント
    • Vue.js (いいね機能、タグ付け機能の実装のため)
    • Scss
  • バックエンド
    • php
    • laravel
  • サーバー
    • nginx
  • DB
    • mysql 5.7(ローカル)
    • RDS(AWS)
  • インフラ
    • AWS
    • ECS/ECR
    • RDS(mysql)
    • EC2
    • S3
    • VPC
    • Route53
    • ALB
    • ACM
  • Terraform(AWSをコード化)
  • heroku(多分AWS版のアプリ完成した後、herokuに移行すると思います。お金無いので)
  • CircleCI

その他Googleアナリティクスの導入

(非技術要件も定義できれば尚良いんですが...)

作成手順

環境設定(Dockerfile→Circle CI,PHPUnit(テスト),Terraform等)→laravelでアプリの中身を作り上げていく→デプロイ の流れ

laravelのインストール

rootディレクトリに移動してlaravelをインストールします

$ composer create-project laravel/laravel larablog 
─── laravel(ルートディレクトリ)
    ├── larablog       ・・・今回のアプリ
        ├── app 
        ├── bootstrap
        .
        .
        .

次回からDockerfileを書いていきます

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

手探りDocker #1

Dockerというものを最近目にするので少しずつやっていこうかと思います。

まったく何が何だかわからないままやり始めます。
ちょろっとdockerとはなんぞや?と事を読んだくらい。
全然頭に入ってません。

導入や理解は以下を参考にさせていただきました。
Docker入門 #1 【Dockerとは】

Dockerインストール

Windows環境なので以下を選択
image.png

英語読めないので翻訳しちゃいました・・・
どうやらDocket Hubからインストーラーを入手する模様
image.png

安定板を選択
image.png

ダウントードできたら、インストールを進めます。
image.png

メモリが4GBのPCのせいか、メモリ不足のエラーがでたので、タスクトレイの赤いアイコンを右クリック
→ Setting → Resources → Memoryを1GBにしました。
image.png

この設定でリスタート

とりあえずこんな画面がでたがよいのだろうか。
image.png

何をすればよいのかわからない・・・
DockerのサイトのGet startedを参考にやってみる
Get started

PowerShellでrun hello-worldをやってみる
image.png

docker image ls や docker container ls -all を打って、なんかダウンロードされていることが確認できます。
image.png

続いてその下のExplore the applicationもやっていきます。

OSイメージ取得

Ubuntu?イメージの取得らしいです。Linux自体もあまり経験がなくて、疎いです・・・
docker run --interactive --tty ubuntu bash

なんかTerminalを表示させたみたいな感じになりました!
image.png

exitすると戻ってこれました。
image.png

WebServer取得

次にnginxというフリーのWebServerを取得します。(初めて聞いた・・・)
docker run --detach --publish 80:80 --name webserver nginx

ファイアーウォールのアクセス許可画面がでてきた!
image.png

実行後、https://localhostにアクセスすると下記が表示されました。
image.png

ポートを指定しなくてよいのは--publish 80:80としているからっぽいですね。

WebServerを停止する際は以下コマンドのようです。
docker container stop webserver

いままでのコマンドの中で --xxx 等がありましたが、それらの日本語説明が以下にあるようです。
Docker-docs-ja

ふとdockerの画面に目をやると以下のように、いままで取得したコンテナ?が表示されてました。
image.png

GUIから、表示されているそれぞれのアイコンをクリックすることで、コンテナの開始や停止、削除等ができるようです。
左から

  • ブラウザで表示
  • CLIを起動
  • Stop
  • Restart
  • Delete

今回はここまでとして
次回はサンプルアプリを動かしてみたいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsチュートリアルの開発環境を Docker でもっと便利にしなイカ!?

【概要】

本記事では、Gem の永続化、データベース及びテスト用メールサーバをコンテナ化していきます。
Railsチュートリアルの開発環境を Docker にしてみなイカ?の続きです。

さて、前回の記事では、Railsチュートリアルの Sample App をコンテナ化しました。
しかし、実際の開発にあたり、煩わしい部分や便利になるところがありますので、改善していきましょう。



【本文】

□ 事前準備

  • 前回の記事と同じファイル及びディレクトリ構成です。
docker/Dockerfile
FROM ruby:2.4.9-alpine3.11

ENV LANG C.UTF-8 \
    TZ Asia/Tokyo

ENV BUILD_PACKAGES="build-base" \
    DB_PACKAGES="sqlite-dev postgresql-dev" \
    RAILS_PACKAGES="tzdata nodejs imagemagick" \
    FAVORITE_PACKAGES="less"

RUN apk update && \
    apk upgrade && \
    apk --update --no-cache add \
        ${BUILD_PACKAGES} \
        ${DB_PACKAGES} \
        ${RAILS_PACKAGES} \
        ${FAVORITE_PACKAGES}

WORKDIR /app

COPY Gemfile \
     Gemfile.lock \
     /app/

RUN bundle install --jobs=4

# 下記のコードは、頻繁に Gemfile を変更する場合、コメントアウトを推奨します。
# RUN apk del ${BUILD_PACKAGES}

# https://github.com/bundler/bundler/issues/6154
ENV BUNDLE_GEMFILE='/app/Gemfile'
docker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    ports:
      - 3000:3000
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
      - ./:/app:cached
    stdin_open: true
    tty: true

□ Gem の永続化

■ 現状の問題点

  • 結論から言うと、現状では Gemfile を編集する度にdocker-compose buildをする必要があリます。つまり、大量の Gem を初めから全てbundle installすることになる煩わしい状態なのです。
  • 理由としては、コンテナの構造によるものであり、この問題点を体験したい場合、事前準備の条件で以下の通り動かしてみると良いでしょう。1
bash(省略可)
 # (1) コンテナのイメージ構築(ここのイメージがコンテナ構築時のデフォルト設定)
 $ docker-compose build

 # (2) コンテナを構築及び起動
 $ docker-compose up -d

 # (3) Gemfile に Gem を追加
  ...
  group :development, :test do
    ...
    gem 'pry-rails'
    gem 'pry-byebug'
  end
  ...

 # (4) 起動済のコンテナ内で bundle install
 $ docker-compose exec app bundle install

 # (5) 追加した Gem が確認できる( /usr/local/bundle/ にインストールされている)
 $ docker-compose exec app gem list

 # (6) コンテナを削除
 $ docker-compose down

 # (7) コンテナを起動すると...
 $ docker-compose up
 > Starting sample_app_app_1 ... done
 > Attaching to sample_app_app_1
 > app_1  | Could not find pry-byebug-3.4.3 in any of the sources
 > app_1  | Run `bundle install` to install missing gems.
 > sample_app_app_1 exited with code 7

 # (8) 結果
 - pry-byebug が見つからないため、bundle install が必要な状態です。
 - つまり、コンテナの状態が(1)に戻ってきていることがわかります。

■ 解決策

  • 前述の通り原因は、起動したコンテナ内で bundle installするだけで、設計図となるコンテナのイメージ自体に反映されていないことです。
  • 解決策としては、Gem をコンテナ外で管理することです。コンテナを削除しても、Gem が存在する場所に影響しません。ここでは、コンテナ外に Gem の保管場所( = volume )を作成して、コンテナ内の Gem を保存する場所と繋げます( = mount )。

  • 参考URL

○ 1: docker-compose.yml に data volume を追加

docker-compose.yml
version: '3'
services:
  datastore:
    image: busybox
+    volumes:
+      - bundle_install:/usr/local/bundle
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    ports:
      - 3000:3000
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
+      - bundle_install:/usr/local/bundle
      - ./:/app:cached
    stdin_open: true
    tty: true
+ volumes:
+   bundle_install:

○ 2: 再度 bundle install

bash
 # 前の手順で、Gemfile に Gem を追加していましたら、該当箇所を一度コメントアウトしてください。

 # (1) コンテナのイメージ構築
 $ docker-compose build

 # (2) コンテナを構築及び起動
 $ docker-compose up -d

 # (3) Gemfile に Gem を追加
  ...
  group :development, :test do
    ...
    gem 'pry-rails'
    gem 'pry-byebug'
  end
  ...

 # (4) 起動済のコンテナ内で bundle install
 $ docker-compose exec app bundle install

 # (5) コンテナを削除
 $ docker-compose down

 # (6) コンテナを起動すると正常に動作しています。
 $ docker-compose up

○ 3: どこに保存されたのか?

  • では、データの保管先を確認してみましょう。
  • 追加した volume は、通常のディレクトリに存在せず、別の場所に存在しています。なお、ディレクトリ内を探検してみると、コンテナも保存していることがわかります。
bash(省略可)
 # Moby VM にアクセス
 $ screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty -s

 # 〜VM内操作へ移行〜

 # 以下のコマンドにより、`sample_app_bundle_install/`の存在が確認できる。
 $ ls /var/lib/docker/volumes/

 # この Volume は、data_store で定義した通り、`/usr/local/bundle`を保存する。
 $ ls /var/lib/docker/volumes/sample_app_bundle_install/_data

 # 終了時
 $ `controll` + `A` + `K`
 $ yes

○ 4: Gem の永続化完了

  • ここまでで、Gem の永続化が完了したため、次はデータベースをコンテナ化します。
  • もちろん、データベースをコンテナ化したとしても、コンテナの削除時にデータベースに保存したデータは失われてしまいます。そのため、Gem の永続化と同様にデータベースも併せて永続化していきます。

□ データベースのコンテナ化

■ 現状の問題点

  • Sample App における本番環境のデータベースは PostgreSQL で、開発環境は SQLite を使用しています。しかし、基本的に開発環境と本番環境は、同一化が求められます。「開発環境では動いたのに本番で動かない(絶望)」ということ自体があってはなりません。
  • しかし、これを実践しようとしてローカル環境で開発するとき、逐一 PostgreSQL を起動したり、プロジェクトによって異なるバージョンを用意する必要があったり、煩わしい部分があるため、コンテナ化します。

  • 参考URL

■ 解決策

○ 1: docker-compose.yml の編集

docker-compose.yml
version: '3'
services:
  datastore:
    image: busybox
    volumes:
      - bundle_install:/usr/local/bundle
+       - db_data:/var/lib/postgresql/data
+   db:
+     image: postgres:12.2-alpine
+     volumes:
+       - db_data:/var/lib/postgresql/data
+     ports:
+       - 5432:5432
+     environment:
+       POSTGRES_USER: root
+       POSTGRES_PASSWORD: pass
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    ports:
      - 3000:3000
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
      - bundle_install:/usr/local/bundle
      - ./:/app:cached
+     depends_on:
+       - db
+     environment:
+       APP_DATABASE_HOST: db
+       APP_DATABASE_USERNAME: root
+       APP_DATABASE_PASSWORD: pass
    stdin_open: true
    tty: true
volumes:
  bundle_install:
+   db_data:

○ 2: config/database.yml の編集

  • Rails の DB 設定は、SQLite のままであるため、PostgreSQL に変更します。
  • なお、ここでは差分表示していませんので、全て置換してください。
config/database.yml
default: &default
  adapter: postgresql
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: <%= ENV.fetch("APP_DATABASE_HOST") { '127.0.0.1' } %>
  port: <%= ENV.fetch("APP_DATABASE_PORT") { '5432' } %>
  username: <%= ENV.fetch("APP_DATABASE_USERNAME") { 'root' } %>
  password: <%= ENV.fetch("APP_DATABASE_PASSWORD") { 'pass' } %>

development:
  <<: *default
  database: sample_app_development

test:
  <<: *default
  database: sample_app_test

production:
  <<: *default
  database: sample_app_production

○ 3: Gemfile の編集

  • 開発環境を PostgreSQL に変更するため、現在の Gemfile の構成もついでに変更しておきます。
Gemfile
...

group :development, :test do
-   gem 'sqlite3', '1.3.13'
  gem 'byebug',  '9.0.6', platform: :mri
  gem 'pry-rails'
  gem 'pry-byebug'
end
...

- group :production do
-   gem 'pg', '0.18.4'
- end
+ gem 'pg', '0.18.4'
...

○ 4: DB コンテナの起動

bash
 # コンテナと volume を削除してから起動
 $ docker-compose down -v
 $ docker-compose up -d

○ 5: データベースの作成

bash
 $ docker-compose exec app rails db:create
 $ docker-compose exec app rails db:migrate
 $ docker-compose exec app rails db:seed

○ 6: DB のコンテナ化完了

  • これで、DB のコンテナ化が完了です。
  • DBコンテナに入って実際に確認したい場合は、次の通り操作してみてください。
bash(省略可)
 # DB コンテナに入る
 $ docker-compose exec db ash

 # PostgreSQL に登録されている Sample App のデータベースに接続
 $ psql -U root -d sample_app_development

 # テーブル生成の確認
 sample_app_development=$ \dt
 sample_app_development=$ exit

□ メールサーバのコンテナ化

■ 現状の問題点

■ 解決策

○ 1: docker-compose.yml の編集

docker-compose.yml
version: '3'
services:
  datastore:
    image: busybox
    volumes:
      - bundle_install:/usr/local/bundle
      - db_data:/var/lib/postgresql/data
  db:
    image: postgres:12.2-alpine
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: pass
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    ports:
      - 3000:3000
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
      - bundle_install:/usr/local/bundle
      - ./:/app:cached
    depends_on:
      - db
    environment:
      APP_DATABASE_HOST: db
      APP_DATABASE_USERNAME: root
      APP_DATABASE_PASSWORD: pass
    stdin_open: true
    tty: true
+   smtp:
+     image: mailhog/mailhog
+     ports:
+       - '8025:8025'
volumes:
  bundle_install:
  db_data:

○ 2: 開発環境のメール設定を編集

config/environments/development.rb
...
  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = true
-   config.action_mailer.delivery_method = :test
-   host = 'railstutorial-yasulab.c9users.io'
-   config.action_mailer.default_url_options = { host: host, protocol: 'https' }
+  config.action_mailer.delivery_method = :smtp
+  config.action_mailer.smtp_settings = {
+    address: "smtp",
+    port: "1025",
+  }
+  config.action_mailer.default_url_options = { host: "localhost:3000" }
...

○ 3: メールサーバのコンテナ化完了

  • これで、メール確認が容易になりました。試しに SignUp してみるとアクティベーションメールが以下のURLに届きます。
  • http://localhost:8025

□ 特記事項

■ 注意事項

  • 今のところ特になし

■ 使用イメージ、ライブラリ

□ おまけ: DB を MySQL にしたい場合

○ 1: Dockerfile の編集

docker/Dockerfile
...
ENV BUILD_PACKAGES="build-base" \
-     DB_PACKAGES="postgresql-dev" \
+     DB_PACKAGES="mysql-client mysql-dev" \
    RAILS_PACKAGES="tzdata nodejs imagemagick" \
    FAVORITE_PACKAGES="less"
...

○ 2: docker-compose.yml の編集

docker-compose.yml
...

+   db:
+     image: mysql:5.7
+     volumes:
+       - db_data:/var/lib/mysql
+     ports:
+       - 3306:3306
+     environment:
+       MYSQL_ROOT_PASSWORD: pass
-   db:
-     image: postgres:12.2-alpine
-     volumes:
-       - db_data:/var/lib/postgresql/data
-     ports:
-       - 5432:5432
-     environment:
-       POSTGRES_USER: root
-       POSTGRES_PASSWORD: pass
...

○ 3: config/database.yml の編集

config/database.yml
default: &default
  adapter: mysql2
  charset: utf8mb4
  collation: utf8mb4_bin
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: <%= ENV.fetch("APP_DATABASE_HOST") { '127.0.0.1' } %>
  port: <%= ENV.fetch("APP_DATABASE_PORT") { '3306' } %>
  username: <%= ENV.fetch("APP_DATABASE_USERNAME") { 'root' } %>
  password: <%= ENV.fetch("APP_DATABASE_PASSWORD") { 'pass' } %>

development:
  <<: *default
  database: sample_app_development

test:
  <<: *default
  database: sample_app_test

production:
  <<: *default
  database: sample_app_production

○ 4: Gemfile の編集

Gemfile
...

-  gem 'pg', '0.18.4'
+  gem 'mysql2', '~> 0.4.4'
...

  1. docker-compose stopstartなら作業状態を継続できることから、Gem もインストール済で作業を継続できる。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsチュートリアルの開発環境を Docker でもっと便利になイカ!?

【概要】

本記事では、Gem の永続化、データベース及びテスト用メールサーバをコンテナ化していきます。
Railsチュートリアルの開発環境を Docker にしてみなイカ?の続きです。

さて、前回の記事では、Railsチュートリアルの Sample App をコンテナ化しました。
しかし、実際の開発にあたり、煩わしい部分や便利になるところがありますので、改善していきましょう。



【本文】

□ 事前準備

  • 前回の記事と同じファイル及びディレクトリ構成です。
docker/Dockerfile
FROM ruby:2.4.9-alpine3.11

ENV LANG C.UTF-8 \
    TZ Asia/Tokyo

ENV BUILD_PACKAGES="build-base" \
    DB_PACKAGES="sqlite-dev postgresql-dev" \
    RAILS_PACKAGES="tzdata nodejs imagemagick" \
    FAVORITE_PACKAGES="less"

RUN apk update && \
    apk upgrade && \
    apk --update --no-cache add \
        ${BUILD_PACKAGES} \
        ${DB_PACKAGES} \
        ${RAILS_PACKAGES} \
        ${FAVORITE_PACKAGES}

WORKDIR /app

COPY Gemfile \
     Gemfile.lock \
     /app/

RUN bundle install --jobs=4

# 下記のコードは、頻繁に Gemfile を変更する場合、コメントアウトを推奨します。
# RUN apk del ${BUILD_PACKAGES}

# https://github.com/bundler/bundler/issues/6154
ENV BUNDLE_GEMFILE='/app/Gemfile'
docker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    ports:
      - 3000:3000
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
      - ./:/app:cached
    stdin_open: true
    tty: true

□ Gem の永続化

■ 現状の問題点

  • 結論から言うと、現状では Gemfile を編集する度にdocker-compose buildをする必要があリます。つまり、大量の Gem を初めから全てbundle installすることになる煩わしい状態なのです。
  • 理由としては、コンテナの構造によるものであり、この問題点を体験したい場合、事前準備の条件で以下の通り動かしてみると良いでしょう。1
bash(省略可)
 # (1) コンテナのイメージ構築(ここのイメージがコンテナ構築時のデフォルト設定)
 $ docker-compose build

 # (2) コンテナを構築及び起動
 $ docker-compose up -d

 # (3) Gemfile に Gem を追加
  ...
  group :development, :test do
    ...
    gem 'pry-rails'
    gem 'pry-byebug'
  end
  ...

 # (4) 起動済のコンテナ内で bundle install
 $ docker-compose exec app bundle install

 # (5) 追加した Gem が確認できる( /usr/local/bundle/ にインストールされている)
 $ docker-compose exec app gem list

 # (6) コンテナを削除
 $ docker-compose down

 # (7) コンテナを起動すると...
 $ docker-compose up
 > Starting sample_app_app_1 ... done
 > Attaching to sample_app_app_1
 > app_1  | Could not find pry-byebug-3.4.3 in any of the sources
 > app_1  | Run `bundle install` to install missing gems.
 > sample_app_app_1 exited with code 7

 # (8) 結果
 - pry-byebug が見つからないため、bundle install が必要な状態です。
 - つまり、コンテナの状態が(1)に戻ってきていることがわかります。

■ 解決策

  • 前述の通り原因は、起動したコンテナ内で bundle installするだけで、設計図となるコンテナのイメージ自体に反映されていないことです。
  • 解決策としては、Gem をコンテナ外で管理することです。コンテナを削除しても、Gem が存在する場所に影響しません。ここでは、コンテナ外に Gem の保管場所( = volume )を作成して、コンテナ内の Gem を保存する場所と繋げます( = mount )。

  • 参考URL

○ 1: docker-compose.yml に data volume を追加

docker-compose.yml
version: '3'
services:
  datastore:
    image: busybox
+    volumes:
+      - bundle_install:/usr/local/bundle
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    ports:
      - 3000:3000
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
+      - bundle_install:/usr/local/bundle
      - ./:/app:cached
    stdin_open: true
    tty: true
+ volumes:
+   bundle_install:

○ 2: 再度 bundle install

bash
 # 前の手順で、Gemfile に Gem を追加していましたら、該当箇所を一度コメントアウトしてください。

 # (1) コンテナのイメージ構築
 $ docker-compose build

 # (2) コンテナを構築及び起動
 $ docker-compose up -d

 # (3) Gemfile に Gem を追加
  ...
  group :development, :test do
    ...
    gem 'pry-rails'
    gem 'pry-byebug'
  end
  ...

 # (4) 起動済のコンテナ内で bundle install
 $ docker-compose exec app bundle install

 # (5) コンテナを削除
 $ docker-compose down

 # (6) コンテナを起動すると正常に動作しています。
 $ docker-compose up

○ 3: どこに保存されたのか?

  • では、データの保管先を確認してみましょう。
  • 追加した volume は、通常のディレクトリに存在せず、別の場所に存在しています。なお、ディレクトリ内を探検してみると、コンテナも保存していることがわかります。
bash(省略可)
 # Moby VM にアクセス
 $ screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty -s

 # 〜VM内操作へ移行〜

 # 以下のコマンドにより、`sample_app_bundle_install/`の存在が確認できる。
 $ ls /var/lib/docker/volumes/

 # この Volume は、data_store で定義した通り、`/usr/local/bundle`を保存する。
 $ ls /var/lib/docker/volumes/sample_app_bundle_install/_data

 # 終了時
 $ `controll` + `A` + `K`
 $ yes

○ 4: Gem の永続化完了

  • ここまでで、Gem の永続化が完了したため、次はデータベースをコンテナ化します。
  • もちろん、データベースをコンテナ化したとしても、コンテナの削除時にデータベースに保存したデータは失われてしまいます。そのため、Gem の永続化と同様にデータベースも併せて永続化していきます。

□ データベースのコンテナ化

■ 現状の問題点

  • Sample App における本番環境のデータベースは PostgreSQL で、開発環境は SQLite を使用しています。しかし、基本的に開発環境と本番環境は、同一化が求められます。「開発環境では動いたのに本番で動かない(絶望)」ということ自体があってはなりません。
  • しかし、これを実践しようとしてローカル環境で開発するとき、逐一 PostgreSQL を起動したり、プロジェクトによって異なるバージョンを用意する必要があったり、煩わしい部分があるため、コンテナ化します。

  • 参考URL

■ 解決策

○ 1: docker-compose.yml の編集

docker-compose.yml
version: '3'
services:
  datastore:
    image: busybox
    volumes:
      - bundle_install:/usr/local/bundle
+       - db_data:/var/lib/postgresql/data
+   db:
+     image: postgres:12.2-alpine
+     volumes:
+       - db_data:/var/lib/postgresql/data
+     ports:
+       - 5432:5432
+     environment:
+       POSTGRES_USER: root
+       POSTGRES_PASSWORD: pass
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    ports:
      - 3000:3000
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
      - bundle_install:/usr/local/bundle
      - ./:/app:cached
+     depends_on:
+       - db
+     environment:
+       APP_DATABASE_HOST: db
+       APP_DATABASE_USERNAME: root
+       APP_DATABASE_PASSWORD: pass
    stdin_open: true
    tty: true
volumes:
  bundle_install:
+   db_data:

○ 2: config/database.yml の編集

  • Rails の DB 設定は、SQLite のままであるため、PostgreSQL に変更します。
  • なお、ここでは差分表示していませんので、全て置換してください。
config/database.yml
default: &default
  adapter: postgresql
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: <%= ENV.fetch("APP_DATABASE_HOST") { '127.0.0.1' } %>
  port: <%= ENV.fetch("APP_DATABASE_PORT") { '5432' } %>
  username: <%= ENV.fetch("APP_DATABASE_USERNAME") { 'root' } %>
  password: <%= ENV.fetch("APP_DATABASE_PASSWORD") { 'pass' } %>

development:
  <<: *default
  database: sample_app_development

test:
  <<: *default
  database: sample_app_test

production:
  <<: *default
  database: sample_app_production

○ 3: Gemfile の編集

  • 開発環境を PostgreSQL に変更するため、現在の Gemfile の構成もついでに変更しておきます。
Gemfile
...

group :development, :test do
-   gem 'sqlite3', '1.3.13'
  gem 'byebug',  '9.0.6', platform: :mri
  gem 'pry-rails'
  gem 'pry-byebug'
end
...

- group :production do
-   gem 'pg', '0.18.4'
- end
+ gem 'pg', '0.18.4'
...

○ 4: DB コンテナの起動

bash
 # コンテナと volume を削除してから起動
 $ docker-compose down -v
 $ docker-compose up -d

○ 5: データベースの作成

bash
 $ docker-compose exec app rails db:create
 $ docker-compose exec app rails db:migrate
 $ docker-compose exec app rails db:seed

○ 6: DB のコンテナ化完了

  • これで、DB のコンテナ化が完了です。
  • DBコンテナに入って実際に確認したい場合は、次の通り操作してみてください。
bash(省略可)
 # DB コンテナに入る
 $ docker-compose exec db ash

 # PostgreSQL に登録されている Sample App のデータベースに接続
 $ psql -U root -d sample_app_development

 # テーブル生成の確認
 sample_app_development=$ \dt
 sample_app_development=$ exit

□ メールサーバのコンテナ化

■ 現状の問題点

■ 解決策

○ 1: docker-compose.yml の編集

docker-compose.yml
version: '3'
services:
  datastore:
    image: busybox
    volumes:
      - bundle_install:/usr/local/bundle
      - db_data:/var/lib/postgresql/data
  db:
    image: postgres:12.2-alpine
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: pass
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    ports:
      - 3000:3000
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
      - bundle_install:/usr/local/bundle
      - ./:/app:cached
    depends_on:
      - db
    environment:
      APP_DATABASE_HOST: db
      APP_DATABASE_USERNAME: root
      APP_DATABASE_PASSWORD: pass
    stdin_open: true
    tty: true
+   smtp:
+     image: mailhog/mailhog
+     ports:
+       - '8025:8025'
volumes:
  bundle_install:
  db_data:

○ 2: 開発環境のメール設定を編集

config/environments/development.rb
...
  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = true
-   config.action_mailer.delivery_method = :test
-   host = 'railstutorial-yasulab.c9users.io'
-   config.action_mailer.default_url_options = { host: host, protocol: 'https' }
+  config.action_mailer.delivery_method = :smtp
+  config.action_mailer.smtp_settings = {
+    address: "smtp",
+    port: "1025",
+  }
+  config.action_mailer.default_url_options = { host: "localhost:3000" }
...

○ 3: メールサーバのコンテナ化完了

  • これで、メール確認が容易になりました。試しに SignUp してみるとアクティベーションメールが以下のURLに届きます。
  • http://localhost:8025

□ 特記事項

■ 注意事項

  • 今のところ特になし

■ 使用イメージ、ライブラリ

□ おまけ: DB を MySQL にしたい場合

○ 1: Dockerfile の編集

docker/Dockerfile
...
ENV BUILD_PACKAGES="build-base" \
-     DB_PACKAGES="postgresql-dev" \
+     DB_PACKAGES="mysql-client mysql-dev" \
    RAILS_PACKAGES="tzdata nodejs imagemagick" \
    FAVORITE_PACKAGES="less"
...

○ 2: docker-compose.yml の編集

docker-compose.yml
...

+   db:
+     image: mysql:5.7
+     volumes:
+       - db_data:/var/lib/mysql
+     ports:
+       - 3306:3306
+     environment:
+       MYSQL_ROOT_PASSWORD: pass
-   db:
-     image: postgres:12.2-alpine
-     volumes:
-       - db_data:/var/lib/postgresql/data
-     ports:
-       - 5432:5432
-     environment:
-       POSTGRES_USER: root
-       POSTGRES_PASSWORD: pass
...

○ 3: config/database.yml の編集

config/database.yml
default: &default
  adapter: mysql2
  charset: utf8mb4
  collation: utf8mb4_bin
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: <%= ENV.fetch("APP_DATABASE_HOST") { '127.0.0.1' } %>
  port: <%= ENV.fetch("APP_DATABASE_PORT") { '3306' } %>
  username: <%= ENV.fetch("APP_DATABASE_USERNAME") { 'root' } %>
  password: <%= ENV.fetch("APP_DATABASE_PASSWORD") { 'pass' } %>

development:
  <<: *default
  database: sample_app_development

test:
  <<: *default
  database: sample_app_test

production:
  <<: *default
  database: sample_app_production

○ 4: Gemfile の編集

Gemfile
...

-  gem 'pg', '0.18.4'
+  gem 'mysql2', '~> 0.4.4'
...

  1. docker-compose stopstartなら作業状態を継続できることから、Gem もインストール済で作業を継続できる。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsアプリをDockerで作ってCircleCIで自動テストしてHerokuにデプロイした話

はじめに

どうも、Pirikaraです。
久しぶりの投稿となりました。

今回は、Docker環境でRailsアプリケーションを開発し、
CircleCIで自動テスト、Herokuにデプロイするところまでやっていきたいと思います。
個人開発でやってみましたが、このエラーの山々......
スクリーンショット 2020-02-20 15.00.43.png

一つ一つエラーを解決して設定ファイルを修正してを繰り返し繰り返し......
やっとまともに動くようになりました。
スクリーンショット 2020-02-20 15.03.12.png

初めてやるよって方は僕の屍を踏み越えていってください。
ちなみに間違ってるよーとか改善点とかご指摘いただけると幸いです。

環境

・Mac OS
・Ruby 2.5.3
・Rails 5.2.2
・MySQL 5.7

また、Dockerがインストールされていることを前提としています(Dockerコマンドが使用できる状態)。
インストールしていない場合は、公式サイトからアカウントを作ってログインし、DockerHubからダウンロード・インストールします。
Dockerhub

Herokuについても登録していない場合は登録の必要があります。
公式サイトから登録が可能です。
Heroku

アプリの構成

スクリーンショット 2020-02-20 13.02.15.png

開発環境からDockerを導入し、RailsとMySQLのimageでコンテナを作りました。苦労していた環境構築がすぐに出来て感動。
GithubにpushするとCircleCIによる自動テストが行われて、テストをパスするとHerokuに自動でデプロイされる仕様です。
また、Herokuでは有料であればMySQLが使用できるみたいですが、僕はお金がないので本番環境のみPostgreSQLを使用します。

では、
1. Docker開発環境の構築
2. CircleCIの導入と自動テスト
3. Herokuに自動デプロイ
の順番でやっていきましょう。

1.Docker開発環境の構築

まず、アプリケーションのディレクトリを作成します。
ここではsample_appとします。

sample_appディレクトリを作成
$ mkdir sample_app

sample_appディレクトリに移動
$ cd sample_app

ディレクトリ内に「Dockerfile」「docker-compose.yml」「Gemfile」「Gemfile.lock」の4ファイルを作成します。

$ touch Dockerfile
$ touch docker-compose.yml
$ touch Gemfile
$ touch Gemfile.lock

今ディレクトリはこんな感じです。
スクリーンショット 2020-02-20 14.16.06.png

では、それぞれ中身を書いていきましょう。(Gemfile.lockは空のままです)

Dockerfile
FROM ruby:2.5.3

#必要なパッケージのインストール
RUN apt-get update -qq && \
    apt-get install -y build-essential \ 
                       libpq-dev \        
                       nodejs           
#作業ディレクトリの作成
RUN mkdir /bbs_app

#作業ディレクトリをAPP_ROOTに割り当てる
ENV APP_ROOT /bbs_app 
WORKDIR $APP_ROOT

#ローカルのGemfileを追加
ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock

#Gemfileのbundle installを実行
RUN bundle install
ADD . $APP_ROOT
docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "4306:3306"

  web:
    build: .
    command: rails s -p 3000 -b '0.0.0.0'
    environment:
      RAILS_ENV: development
    volumes:
      - .:/bbs_app
    ports:
      - "3000:3000"
    links:
      - db
Gemfile
source 'https://rubygems.org'
gem 'rails', '5.2.2'

ところどころ違いますが、
設定の内容についてはこちらの記事が詳しくて参考になったので、任せます。
DockerでRuby on Railsの環境構築を行うためのステップ【Rails 6対応】

ここまで書けたら、dockerコマンドでrails newします。

$ docker-compose run web rails new . --force --database=mysql --skip-bundle

あとでimageを構築する際にDockerfileにしたがってbundle installが実行されるので、ここではスキップします。

作成されたconfig/database.ymlを編集します。

database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password # docker-compose.ymlのMYSQL_ROOT_PASSWORD
  host: db # docker-compose.ymlのservice名

dockerを起動します。

imageを構築(コンテナは作成しない)
$ docker-compose build

コンテナを構築・起動
$ docker-compose up

データベースを作成します。

$ docker-compose run --rm web rails db:create

--rmオプションをつけることで、コンテナが実行されたあと削除されます。
「rails g controller ~」や「rails console」など、docker-composeから始まるコマンドで実行していくことになりますが、
--rmをつけていないと実行するたびにコンテナが増えていってしまうので、都度削除しています。僕は。

ここまでできると、localhost:3000へアクセスしてサーバーの起動を確認することができます。おめでとう。
スクリーンショット 2020-02-20 14.42.11.png

2.CircleCIの導入と自動テスト

こちらのブログをパク・・・参考にしました。
導入まで大変わかりやすく、参考になりました。こちらを参考に導入してみてください。

ウェブ系ウシジマくんのテックブログ

「.circleci」というディレクトリを作成し、これ以下に「config.yml」というファイルを作成します。
また、configディレクトリ以下に「database.yml.ci」というファイルを作成します。

こんな感じ。
スクリーンショット 2020-02-20 14.56.46.png

では、作成したファイルの中身を書いていきましょう。

config.yml
version: 2
jobs:
  build:
    docker:
    - image: circleci/ruby:2.5.3-node-browsers
      environment:
        - BUNDLER_VERSION: 2.0.2
        - RAILS_ENV: 'test'
    - image: circleci/mysql:5.7
      environment:
        - MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
        - MYSQL_ROOT_HOST: '127.0.0.1'

    working_directory: ~/bbs_app


    steps:
    - checkout

    - restore_cache:
        keys:
        - v1-dependencies-{{ checksum "Gemfile.lock" }}
        - v1-dependencies-

    - run:
        name: install dependencies
        command: |
          gem install bundler -v 2.0.2
          bundle install --jobs=4 --retry=3 --path vendor/bundle

    - save_cache:
        paths:
        - ./vendor/bundle
        key: v1-dependencies-{{ checksum "Gemfile.lock" }}

    # Database setup
    - run: mv ./config/database.yml.ci ./config/database.yml

    # Database setup
    - run:
        name: Databasesetup
        command: |
           bundle exec rake db:create
           bundle exec rake db:schema:load

    # run tests!
    - run:
        name: Run rspec
        command: |
          mkdir /tmp/test-results
          TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
            circleci tests split --split-by=timings)"

          bundle exec rspec \
            --format progress \
            --format RspecJunitFormatter \
            --out /tmp/test-results/rspec.xml \
            --format progress \
            $TEST_FILES

    # collect reports
    - store_test_results:
        path: /tmp/test-results
    - store_artifacts:
        path: /tmp/test-results
        destination: test-results
database.yml.ci
test:
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: 'root'
  port: 3306
  host: '127.0.0.1'
  database: app_test #database.ymlのテスト環境のデータベース名を参照

これでGithubへpushすると、自動でテストが実行されるようになります。
プルリクエストを作ってmasterブランチへmergeしていくと思うのですが、テストに失敗するとmergeすることができません。
スクリーンショット 2020-02-20 19.50.23.png
ほらね。

Detailのリンクからエラー箇所も教えて頂けます。
スクリーンショット 2020-02-20 19.54.06.png

テストをパスすると、Mergeボタンがアクティブになります。
スクリーンショット 2020-02-20 20.00.18.png

※ seeds.rbを読み込みたい場合

.circleci/config.ymlでseeds.rbの読み込み設定をしたところ、うまくいかなかったのでspec_helperにseeds.rbを読み込む設定をしました。

「database_cleaner」というgemを導入し、spec_helperへ処理を書いていきます。
これで、Rspec実行の際にデータベースがリフレッシュされ、seeds.fileが読み込まれます。

Githubへpushした際に実行された場合は大丈夫なのですが、ローカルでdocker-composeコマンドからrspecを実行した場合にデータベースがリセットされてしまうので注意してください。

Gemfile
group :development, :test do
  # rspec実行時にDBをリセットする
  gem 'database_cleaner'
end
spec_helper.rb
# テスト実行時にDatabaseをリセットし、seeds.rbを読み込む
RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
    Rails.application.load_seed
  end
end

3.Herokuに自動デプロイ

Herokuにデプロイするため、ファイルを修正・追加します。

まずはGemfile。
開発環境ではMySQL、本番環境ではPostgeSQLを使用するので、「pg」のgemをインストールします。

Gemfile
# 変更前
gem 'mysql2', '>= 0.4.4', '< 0.6.0'

# 変更後
gem 'mysql2', '>= 0.4.4', '< 0.6.0', groups: %w(test development), require: false
gem 'pg', '~> 0.19.0', group: :production, require: false

次に、database.ymlを編集していきます。
本番環境でPostgreSQLを使う設定をします。

database.yml
production:
  <<: *default
  adapter: postgresql
  encoding: unicode
  pool: 5

そして、「heroku.yml」というファイルを新たに作成します。
作成場所はアプリ直下です。(GemfileとかDockerfileと一緒)
今回はDockerコンテナを使用して開発をしているので、コンテナごとHerokuのサーバーに持っていきます。
そのための設定ファイルです。知らんけど。

DockerコンテナをHerokuにアップする方法は公式サイトを参考にしました。

Dockerを使用したデプロイ

heroku.yml
build:
  docker:
    web: Dockerfile
run:
  web: bundle exec puma -C config/puma.rb

アプリケーション側の設定はこれで完了です。

ではHeroku側の設定をしてデプロイしていきましょう。
ターミナルから、Herokuにログインします。

$ heroku login

# ログインするかどうか確認されます。
# クリックするとブラウザが立ち上がり、Herokuのログイン画面になります。ログインしてください。
heroku: Press any key to open up the browser to login or q to exit: 

# ログインが完了すると、ターミナルに「ログインしたよー」って表示されます。
Opening browser to https://cli-auth.heroku.com/auth/browser/**************
Logging in... done
Logged in as *******@email.com

次に、Herokuにアプリケーションを作成します。

# アプリケーション名のところには好きな名前を入れてください。それでURLが作成されます。
$ heroku create アプリケーション名

Creating app... done, ⬢ *******
https://******.herokuapp.com/ | https://git.heroku.com/*******.git

ちなみにこの時、Herokuのリポジトリが作成されています。
もしアプリケーションの名前を変更したいときは、Herokuの管理画面から名前を変更することに加えて、リポジトリを削除する必要があります。

$ git remote rm heroku

このコマンドで消せます。
消さないとアプリ名とリポジトリ名が異なるためにデプロイできなくなります。

そして、Heroku側でPostgreSQLを使用する設定をします。

$ heroku addons:create heroku-postgresql:hobby-dev

# PostgreSQLのデータベース作ったよーって通知がきます。
Creating heroku-postgresql:hobby-dev on ⬢ ******... free
Database has been created and is available
 ! This database is empty. If upgrading, you can transfer
 ! data from another database with pg:copy
Created postgresql-transparent-70433 as DATABASE_URL
Use heroku addons:docs heroku-postgresql to view documentation

今回DockerコンテナをHerokuにのせるので、Heroku側でコンテナにアプリのStackをセットします。

$ heroku stack:set container

この辺の話は「heroku.yml」の設定の時に出てきた公式サイトに全部載ってます。
Dockerを使用したデプロイ

これでデプロイするための設定は完了しました。
masterブランチにアプリをpushしたのち、

$ git push heroku master

このコマンドでHerokuのリポジトリにpushすることでデプロイが完了します。エラーが起こらなければ。

さて、ついに自動デプロイです。
circleciを通してHerokuにデプロイしていくので、config.ymlファイルにdeployの処理を追加します。

config.yml
# 省略
    - deploy:
        name: Deploy Master to Heroku
        command: |
          if [ "${CIRCLE_BRANCH}" == "master" ]; then
            git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git master
          fi

「HEROKU_API_KEY」と「HEROKU_APP_NAME」については、CircleCIに設定した環境変数が読まれるため、
こちらを設定していきます。

どちらもHerokuの管理画面から取得できます。

アカウント設定からHEROKU_API_KEYに当たるAPI KEYを......
スクリーンショット 2020-02-20 18.47.58.png

アプリケーションの設定からHEROKU_APP_NAMEを......
スクリーンショット 2020-02-20 19.28.44.png
それぞれ取得します。

CircleCIのアプリケーション管理画面から、右上の「Project Setting」をクリックします。
スクリーンショット 2020-02-20 19.30.15.png

Environment Variablesから「Add Variables」をクリックして、先ほど取得した値を環境変数として設定します。
これがconfig.ymlで使用されます。
スクリーンショット 2020-02-20 19.33.39.png

設定は以上です。
これで、

Githubへpush → CircleCiが自動でテスト → パスすればHerokuに自動でデプロイ

という風に動きます。良かったね。

終わりに

DockerとCircleCIを利用したのは初めてでしたが、
環境構築もテスト・デプロイも簡潔になったので、非常に便利でした。

特にテストコマンドやデプロイコマンドについては「コマンド打つだけやしなぁ......」と自動化の恩恵を甘く見ていましたが、
チリも積もればなんとやらです。
いちいちコマンドを打つ煩わしさから解放され、アプリの開発スピードも段違いだったように感じます。

参考にしていただけたら幸いです。

またね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker system pruneでも上手くいかない時のoverlay2の掃除用スクリプト

問題

  • /var/lib/docker/overlay2 が肥大化
  • 特にデータを大量に使っているimage, containerはない
  • docker system df の合計値は数十GBにも関わらず、 overlay2 の合計は数百GBある
  • docker system prune 系のコマンドを打っても解決せず

考えられる原因

このコメントによると、古いバージョンで docker rm -f を実行した際にlayerが削除されないことがあるよう。

(overlay2配下のディレクトリが正確に1 layerなのか知らないですが、ここではlayerと呼びます)

解決策

inspectコマンドで今あるimage, containerが使ってるlayerを洗い出して、 /var/lib/docker/overlay2 と比較する。

スクリプト

chmod +x で実行権限を付与しておく

used_layers.sh
#!/bin/sh

expr='s;/var/lib/docker/overlay2/\(.*\)/.*;\1;g'

print_layers () {
  data=`echo $1 | jq '.[0].GraphDriver.Data'`

  # この3つは必要なさそう
  echo $data | jq -r '.MergedDir' | sed -e "$expr"
  echo $data | jq -r '.UpperDir' | sed -e "$expr"
  echo $data | jq -r '.WorkDir' | sed -e "$expr"

  for dir in `echo $data | jq -r '.LowerDir' | tr ':' ' '`
  do
    echo $dir | sed -e "$expr"
  done
}

docker images | tail -n +2 | while read -r line
do
  image=`echo $line | awk '{print $1}'`
  tag=`echo $line | awk '{print $2}'`
  print_layers "`docker image inspect $image:$tag`"
done

for container_id in `docker ps | awk '{print $1}' | tail -n +2`
do
  print_layers "`docker container inspect $container_id`"
done

diff_layers.sh
#!/bin/sh

./used_layers.sh | sort | uniq > used_layers.txt
ls /var/lib/docker/overlay2 > all_layers.txt

comm -13 --nocheck-order used_layers.txt all_layers.txt > diff_layers.txt

実行

まだ試したことないので自己判断でお願いします

# 3つのファイルが生成される
# used_layers.txt: 現在あるimage, containerで使われているlayer一覧
# all_layers.txt: /var/lib/docker/overlay2 内にあるdirectory一覧
# diff_layers.txt: all_layers.txtにあってused_layers.txtにないもの一覧
./diff_layers.sh

# 差分を削除
sed -e 's;^;/var/lib/docker/overlay2/;' diff_layers.txt | xargs rm -rf
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ECSにおいてdocker runコマンドの-t,--ttyオプションに相当する設定をした話

はじめに

こんにちは。
現在私は社内のデータ分析基盤の刷新に取り組んでおります。

今回は検証中のDataSunriseをECSに乗せるべくを試行錯誤を行っていた中で発見した、
docker runコマンドの-t,--ttyオプションに相当するであろう設定をECSで行う方法について記載します。

DataSunriseについてはこちらをご参照下さい。

事の起こり

localでできることがECSでできない

検証のためにlocal環境にてコンテナを立てていました。
docker run -itd -p 11000:11000 [datasunrise image id](local環境にて)
この場合は期待通りコンテナが立ち上がり、https://[グローバルIP]:11000で繋ぐことができました。

これをECSで実現したかったのですが、ECSのタスクは即時終了し、
CloudWatchLogsに流れてくるのはservice is started.のメッセージのみでした。

試しにlocal環境にて、
docker run [datasunrise image id]を実行してみると、
service is started.との表示のみでコンテナは即時終了していました。
(本メッセージはDataSunriseコンテナが起動、即時終了した際に残すログのようです。)

結果的にECSにおいてdocker runコマンドの-t,--ttyオプションに相当するようなことを設定しなければならないと判断しました。

結論

タスク定義においてpseudoTerminaltrueにすることで、コンテナを起動させ続けることができました。
なお、本問題を解決に導いて下さった記事はこちらのstackoverflowです。

具体的な設定方法は次の通りです。

設定方法

GUIでの設定方法を記載します。
最終的にJSONをいじることになるのでCLIで設定する場合も対応可能ではないかと思います。

  1. 対象のECSタスク定義を開く
    image.png

  2. JSONによる設定を押下
    image.png
    ページ最下部に存在します。(画像赤枠部分)

  3. pseudoTerminalをtrueに変更
    image.png
    初期設定でnullとなっていましたが、trueに書き換えて保存を押せば適用できました。(EC2/Fargateともに適用可能)
    *こちらは説明用画像ですので、当該箇所以外は環境に合わせてよしなに設定下さい。念の為。

まとめ

ECSにおいてdocker runコマンドの-t,--ttyオプションに相当するであろう設定ができました。
今回は試行錯誤段階において、stackoverflowに行き着いた事によって解決したのですが、
よくよく公式ドキュメントを読んでみると

pseudoTerminal
Type: Boolean

Required: no

When this parameter is true, a TTY is allocated. This parameter maps to Tty in the Create a container section of the Docker Remote API and the --tty option to docker run.

という記載がありました。

ちゃんと公式ドキュメント読みましょうという教訓でした。。。

参考

また、試行錯誤段階にて以下記事も参考にさせて頂きました。ありがとうございます。
Dockerのコンテナを起動したままにする

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6のdocker-compose環境をwebpackerまで含めて構築する

Rails6のSoftware Stack

今回は以下の内容で構成します

  • Ruby 2.6.5
  • Rails 6.0.2
  • Postgresql 11.6
  • Redis 3.2.11
  • Nodejs 12.14.0
  • yarn 1.21.1
  • Bundler 2.1.3

サンプルプロジェクトは以下で提供しています
こちらでは、bootstrapのsassの、変数を変更してホットリロードするところまで確認できるかと思います

Dockerfile

Dockerfileでは以下のように、Rails6から必須になったyarnを入れておきます。
ここでは、Dockerfileでは主に以下の作業を行わせています。

  • node, ruby, yarnの設定
  • bundlerをglobalにインストール
  • entrypoint.shの設定
  • ロケールの設定
Dockerfile
FROM node:12.14.0 as node
FROM ruby:2.6.5

RUN apt-get update -qq && apt-get install -y postgresql-client && \
    apt-get install -y locales

COPY --from=node /usr/local/bin/node /usr/local/bin/node
COPY --from=node /usr/local/include/node /usr/local/include/node
COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
RUN ln -s /usr/local/bin/node /usr/local/bin/nodejs && \
    ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm

ENV YARN_VERSION 1.21.1

COPY --from=node /opt/yarn-v$YARN_VERSION /opt/yarn
COPY --from=node /usr/local/bin/node /usr/local/bin/

RUN ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
    && ln -s /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg

ENV BUNDLER_VERSION 2.1.3

RUN gem install bundler -v $BUNDLER_VERSION

RUN mkdir -p /var/www/app
WORKDIR /var/www/app

# Add a script to be executed every time the container starts.
COPY ./docker/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

RUN locale-gen ja_JP.UTF-8
# timezoneをJSTに変更
RUN apt-get install -y tzdata \
  && rm /etc/localtime \
  && ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
  && dpkg-reconfigure -f noninteractive tzdata
# キャッシュ削除
RUN rm -rf /var/lib/apt/lists/*
EXPOSE 3000

docker-compose.yml

  • docker-composeでは、アプリケーションとwebpackerを起動しておきます
  • webpackerでコンパイルされたJSは public/packs 以下に配置されます
  • wait-for-it.shを使って、webpackにはアプリケーションが起動するのを待ってもらっています
  • .env.example から .env にコピーしてローカル側のポートを変更できるようにしています
  • ここでは起動時に bundle installyarn install を行っていますが、好みで変更してください
docker-compose.yml
version: '3'
services:
  app: &app_base
    build: "."
    stdin_open: true
    tty: true
    ports:
      - $HTTP_PORT:3000
    command: /bin/sh -c "bundle install && yarn install --check-files && bundle exec puma -C config/puma.rb"
    environment:
      RAILS_ENV: $RAILS_ENV
      NODE_ENV: $RAILS_ENV
      # .bundle/config を gitに含めて提供してください
      BUNDLE_APP_CONFIG: ./.bundle
      DB_USER: pguser
      DB_PASS: pgpass
      DB_HOST: postgres
      DB_PORT: 5432
      REDIS_URL: redis://redis:6379
    volumes:
      - .:/var/www/app
      - bundle:/var/www/app/vendor/bundle
      - node-modules:/var/www/app/node_modules
      - packs:/var/www/app/public/packs
    depends_on:
      - postgres
      - redis
  webpack:
    <<: *app_base
    command: /bin/sh -c "docker/wait-for-it.sh app:3000 --timeout=600 && bundle install && yarn install --check-files && bin/webpack-dev-server"
    environment:
      NODE_ENV: $RAILS_ENV
      RAILS_ENV: $RAILS_ENV
      BUNDLE_APP_CONFIG: ./.bundle
      WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
    ports:
      - $WEBPACK_PORT:3035
    tty: true
    stdin_open: true
    depends_on:
      - app

  postgres:
    stdin_open: true
    tty: true
    restart: always
    image: postgres:11.6
    ports:
      - $DB_PORT:5432
    environment:
      POSTGRES_USER: pguser
      POSTGRES_PASSWORD: pgpass
      TZ: Asia/Tokyo
    volumes:
      - pgsql-data:/var/lib/postgresql/data

  redis:
    restart: always
    image: redis:3.2.11
    environment:
      TZ: Asia/Tokyo
    ports:
      - $REDIS_PORT:6379
    command: redis-server --appendonly yes

volumes:
  pgsql-data:
  bundle:
  node-modules:
  packs:

application.html.erbでpack_tagを使うよう変更する

  • Rails 6: the missing developer setup guideを参考に、application.html.erbpack_tag を使うように変更しておいてください
  • data-turbolinks-trackreloadになっていることも確認してください
application.html.erb
    <%= stylesheet_pack_tag "application", media: "all", "data-turbolinks-track": "reload" %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

webpacker.yml を docker-composeに合わせて変更する

  • webpackerの設定ファイルを、docker-composeのservice名に合わせて変更します
  • また、HMR(Hot Module Replacement)の設定を有効にしてホットリロードできるようにしておきます
config/webpacker.yml
  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    host: webpack # docker-composeのservice名に合わせて変更
    hmr: true # ホットリロードできるようにする

起動とホットリロード

  • 以上でdocker-compose upでサービスを起動すれば、アプリケーションとwebpack-dev-serverが動作するかと思います
  • bootstrapなど、コンパイルが必要なassetsを追加して、変数などを変更すれば、画面をリロードすることなく、色などの変更が行えます

webpacker と sprockets

Rails6で導入された webpacker と、既存の sprockets について以下は必読です。
読まずにpack周りでJSを書くと、かなり回り道をすることになるかと思います。
長文にお付き合いいただきありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker desktop ver 2.2、insecure-registriesどこ行ったんだ問題

前のバージョンまではPreferences -> AdvancedでGUIから設定できたinsecure-registriesですが、v2.2になって設定のGUIが大きく変わったあげく、見つからない……

と思ったら、ここでした。
image.png
JSON形式でホストを指定してあげてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker入門|基本コマンド等

インストール

Docker

$ brew install docker docker-machine

Docker Compose

$ brew install docker-compose

状況確認

起動中コンテナ確認

$ docker ps

停止中を含む全てのコンテナ確認

$ docker ps -a

コンテナの稼働確認

$ docker stats

現状のイメージの確認

$ docker images

イメージの詳細確認

$ docker inspect [オプション] [コンテナ識別子またはイメージ識別子]

Docker のバージョン確認

$ docker -v

Docker Compose のバージョン確認

$ docker-compose -v

Dockerの実行環境確認

$ docker info

生成/起動

コンテナの生成+起動

$ docker run [オプション] イメージ名[:タグ名] [引数]

コンテナの起動

$ docker start [オプション] [コンテナ識別子]

コンテナの再起動

$ docker restart [オプション] [コンテナ識別子]

DockerfileからDockerイメージの作成

$ docker build -t [生成するイメージ名]:[タグ名] [Dockerfileの場所]

[Dockerfileの場所]は、ビルドコンテキストの指定でもある。

--no-chash オプションをつけると、ビルド済みの部分もビルドし直す。

Docker Compose からの起動

$ docker-compose up -d

Docker Compose からDockerイメージの作成

$ docker-compose build

停止

コンテナの停止

$ docker stop [コンテナIDもしくはコンテナ名]

一括停止の場合は以下のコマンド

$ docker stop $(docker ps -q)

Docker Compose からの停止

$ docker-compose stop

削除

コンテナの削除

$ docker rm [コンテナID]

コンテナIDの複数指定OK

一括削除の場合は以下のコマンド

$ docker rmdocker ps -a -q``

docker ps -a -q は、コンテナIDの一覧表示

イメージの削除方法

$ docker rmi [イメージID]

イメージの前にコンテナを削除する必要あり。

forceオプション(以下)で強制削除も可能。ただしコンテナは残る。

$ docker rmi -f [イメージID]

※削除時は順番を考慮する必要あり

削除を行う際は、下記順番を考慮して作業をすすめる必要あり。

  1. 起動中のコンテナを停止する
  2. 停止中のコンテナ
  3. Dockerイメージ

(理由)
- 起動中のコンテナは削除できない
- コンテナが存在すると、そのコンテナで使用しているイメージは削除できない

その他

Docker Hubへのログイン

$ docker login

Docker Hubへのイメージアップロード

$ docker push イメージ名[:タグ名]

Docker Hubからのログアウト

$ docker logout

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-composeで起動中のログにアタッチする方法

docker-compose up -d $serviceName でコンテナを起動した時、logの出力を確認するには
docker-compose logs $serviceNameで確認できる
ただこの場合だとそれ以降のlogを取得するには再度同じコマンドを打たなければならない

docker-composeででタッチ起動したコンテナのlogを出力させ続けるには以下のコマンドを打つ

docker-compose logs -f $serviceName

-fまたは--followオプションをつけることでその後もログを出力させ続けることができる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(IT業界における)新型コロナウィルス対策(案)組織編

(IT業界における)新型コロナウィルス対策(案)個人編
https://qiita.com/kaizen_nagoya/items/f6996fe6d49ee6095d61

に対応した組織編です。

個人による新型コロナウィルス対策の周知

1 手洗い前の素手で直接、口、鼻、目を触らない。
2 手洗い
3 咳・くしゃみ時推奨習慣
4 健康管理(免疫力・抵抗力の保持)
を周知

1 手洗い前の素手で直接、口、鼻、目を触らない。

マスクをする理由の一つでもある。
手洗いが必要な理由の一つでもある。

 2 手洗い

出勤時、昼食前、昼食後、退勤時の4度は最低限。
用便の際に前後で手洗いを推奨するかどうか、組織で判断。

 3 咳・くしゃみ時推奨習慣

マスクをする理由の一つでもある。

4 健康管理(免疫力・抵抗力の保持)

手洗い場の確保

空間

建築系の法規で、何人いる場合に、手洗い場の大きさ、種類などについて推奨がある。

時間

朝の出勤時の手洗いを励行しようとしても、人数分手洗い場が確保できない場合は、
出勤時間をばらけさせるとよいかもしれない。昼休みの始まり、終わりにも手洗いを励行する。

手洗い時間は、事業の継続性にとっては業務時間と見做すのが妥当かもしれない。

清掃

共用の机などは、水拭きだけでなく、アルコール消毒なども励行するとよい。

旅館などの生活衛生関係営業におけるSARS感染防止対策のための自主管理マニュアル
http://www.seiei.or.jp/db-pdf/sars_01.pdf

  • トイレの流水レバー、便座、フタは、台所用合成 洗剤の希釈液に浸した雑巾で二度拭きする。
  • 便器の内側は、台所用合成洗剤の希釈液を用 いて、トイレ清掃用のブラシ(スポンジブラシなど) で周囲に飛び散らないように清掃し、フタをして5 分以上経過してからフタをしたままフラッシュする。 なお、使用したブラシは台所用合成洗剤の希釈液又はやや濃いめの希釈液の中に5分以上漬けておく。
  • 体液や汚物によって汚れたモノの消毒 体液や汚物によって汚れた部分は、台所用合成洗 剤の希釈液、あるいはこれに十分浸したティッシュペー パーなどで汚染されたところを覆い、5分以上経過し てから、から拭きする。
  • 利用客が触れた可能性のあるモノの消毒 ドアノブ、エレベーターの押しボタン、エスカレータ ーや階段の手摺りなどは、台所用合成洗剤の希釈液 に浸した雑巾で二度拭きする。

作業上の留意

- 作業開始前
清掃従業員等は作業前に必要に応じてサージカルマスクなどの感染防御可能なマスク(以下 「感染防御マスク」という。)やゴム手袋、ゴーグル、使い捨てガウン、エプロン、汚染除去可能な履物で個人防御をすること。
- 作業終了後
○ 清掃・消毒終了後は、石鹸による手指の手洗いや速乾性皮膚消毒剤(エタノール等)を用いた手指の消毒を行うとともに、うがいを励行すること。
○ 使用後の感染防御マスク等は、回収されたゴミ等と一緒にビニール袋で密閉し焼却等適正な方法で廃棄すること。

健康管理

通勤時間等拘束時間の削減のため在宅勤務を可能にする。

混雑した通勤時間を避けるため、フレックスタイムを可能にする。

食事時間を近隣とずらして、混雑した食事を避ける。

遠隔業務

github/gitlab/bitbucket

git系のサービスで、private接続可能な範囲設定をどのようにするかは、ネットワーク管理者とご相談ください。

個々の企業での、ネットワーク接続方法は、千差万別で、どうしたらいいか、一般論では妙案がありません。

cloud

amazon, google, microsoftなどのcloud利用について、組織外かrの接続については、ネットワーク管理者と各接続サービス会社とご協議ください。

Office 365等

Office 365, Teams など、ID, Password管理している場合に、管理方法

docker等

cloudサービスとの連携など、ネットワーク管理者と各接続サービス会社とご協議ください。

テレビ会議

skype

https://www.skype.com/ja/features/calling-and-instant-messaging/#calls

使用するデバイスに関係なく最大 50 名 (自分に加えて 49 名) が参加できる 電話会議またはビデオ会議を開催できます。

teams

Microsoft Teams
Office 365 でチームワークを実現するハブ
https://products.office.com/ja-jp/microsoft-teams/group-chat-software

webEX

https://www.cisco.com/c/m/ja_jp/solutions/webex.html

zoom

https://zoom.us/jp-jp/meetings.html

行事の遠隔開催

あらかじめ遠隔開催を想定していた事業であれば、
講師の方と綿密な著作権上の取り決めをしておくことができる。

集合開催を遠隔開催に変更する場合には、
講師の方と著作権を含めて、交渉事項が多岐に渡る。

 講師の登壇条件区分(案)
講師の所属組織、講師個人の判断を尊重し、下記の区分に回答をもらう。

直接登壇またはオンライン登壇の別。(直接・オンライン(動画・音声・文字))
・オンライン登壇の場合の動画の記録の可否。(可・否)
・動画でのインタネットへの配信の可否。(可・否)
・・動画の再上映(インタネットを覗く)の可否。可の場合は再上映回数。(可( 回)・否)
動画の再上映可の場合でも、再上映日程、場所については事前にご相談いたします。

行事開催時の注意事項(新型コロナウイルス・インフルエンザ等流行時を含む)
https://qiita.com/kaizen_nagoya/items/92fe0b8076111a3c1bc4

文書履歴(document history)

ver. 0.01 初稿 20200220 午後4時
ver. 0.02 行事追記 20200220 午後5時

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Kubernetes + Envoyでクラスタ内からクラスタ外のサーバーへの接続をロードバランシングする

Kubernetesのクラスタ内のPodからクラスタ外にあるMySQLなどのサーバに接続するときには、Envoyを使うと良さそうという話です。

まだ運用はしていませんが、設定方法を載せるので迷っている方の参考になったら幸いです。

Envoyを選択する理由

要件にもよりますが、次のような理由からです。

  • productionやstagingなどの環境によりMySQLの接続先を自由に切り替えたかったので、ELBやEC2上でプロキシを立てるのではなく、サイドカーコンテナを立てる方向で考えていた
  • 今回は、マイクロサービスを構築するわけではなかったため、Istioはtoo muchと判断した
  • HAProxyやnginxはこちらの比較記事を読んだ結果、除外した
  • KubernetesのNon-selector Serviceを使うという手もあるが、手元で検証したところヘルスチェックが動作しなかった。(もしかしたらやりようはあるのかもしれません)

構成図

image.png

設定内容

envoyの設定はconfigmapにまとめています。

envoy-configmap.yml
kind: ConfigMap
apiVersion: v1
metadata:
  name: envoy-conf
data:
  envoy.yaml: |
    static_resources:
      listeners:
      - name: mysql_listener
        address:
          socket_address:
            address: 0.0.0.0
            port_value: 3306
        filter_chains:
        - filters:
          - name: envoy.filters.network.mysql_proxy
            typed_config:
              "@type": type.googleapis.com/envoy.config.filter.network.mysql_proxy.v1alpha1.MySQLProxy
              stat_prefix: egress_mysql
          - name: envoy.filters.network.tcp_proxy
            typed_config:
              "@type": type.googleapis.com/envoy.config.filter.network.tcp_proxy.v2.TcpProxy
              stat_prefix: mysql_tcp
              cluster: mysql_cluster

      clusters:
      - name: mysql_cluster
        connect_timeout: 1s
        health_checks:
        - healthy_threshold: 3
          interval: 5s
          tcp_health_check: {}
          timeout: 1s
          unhealthy_threshold: 3
        type: strict_dns
        load_assignment:
          cluster_name: mysql_cluster
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: **.**.**.** # ここにそれぞれのMySQLのIPアドレスを設定する
                    port_value: 3306
            - endpoint:
                address:
                  socket_address:
                    address: **.**.**.** # ここにそれぞれのMySQLのIPアドレスを設定する
                    port_value: 3306

    admin:
      access_log_path: "/dev/null"
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 8001

Podの設定は、nginx+php-fpmのサイドカーとしてEnvoyを追加しています。

api.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      hostname: myhostname
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
      - name: php-fpm
        image: phpfpm:latest
        ports:
        - containerPort: 9000
      - name: envoy-proxy
        image: envoyproxy/envoy-dev:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 3306
          name: proxy-mysql
          protocol: TCP
        resources:
          limits:
            cpu: 0.5
            memory: 1Gi
        volumeMounts:
          - name: envoy-conf
            mountPath: /etc/envoy/envoy.yaml
            subPath: envoy.yaml
      volumes:
        - name: envoy-conf
          configMap:
            name: envoy-conf
            items:
              - key: envoy.yaml
                path: envoy.yaml
                mode: 0644
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
  labels:
    app: nginx
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
    - name: https
      port: 443
      targetPort: 80
  type: LoadBalancer
  selector:
    app: nginx

この設定により、php-fpmのコンテナから0.0.0.0:3306に接続するとMySqlに繋がります。

まとめ

Kubernetesのクラスタに外部から接続する方法は、ネットで探すと色々出てくるのですが、クラスタから外部サーバに接続する方法についての情報はあまりない印象だったので書くことにしました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockeでminioを立ち上げる

OSはubuntu 18.04 LTS。
dockerでminioをセットアップする。
dockerの設定を一括でできる便利なdocker-composeを使う。

準備

docker-compose.ymlが必要なので、準備する。

$ mdkir minio
$ cd minio
$ mkdir data
保存先のストレージを用意する。
dataディレクトリ(パスは/home/hoge/data)が生成された。
$ vi docker-compose.yml
version: '3.7'
services:
  minio1:
    image: "minio/minio"  # docker hubにあるminio/minioイメージをpullする
    volumes:
      - /home/hoge/minio/data:/data
    ports:
      - 9000:9000
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server /data

これでとりあえず準備完了。

doker hubにあるminioイメージをpull

docker-compose upでもpullされるが、ここではpullからしておく。公式でもそうしている。

$ docker-compose pull
docker hubにあるminio/minioがpullされる。
$ docker images
minio/minioが保存されていることを確認できるはず。

minioコンテナの起動

$ docker-compose up

戻ってこないので、別のターミナルでコンテナを確認すると、実行できていることを確認できる。

$ docker ps
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntu18.04LTSにDockerをインストールする

Ubuntu18.04 LTSにDockerとdocker-composeをインストールする。

apt-getでのインストール

公式に詳細が書いてあるので、簡単に記載する。
https://docs.docker.com/install/linux/docker-ce/ubuntu/

1. 古いバージョンのアンインストール

$ sudo apt-get remove docker docker-engine docker.io containerd runc

2. 必要なパッケージをインストール

$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

3. Dockerの公式GPGキーの入手

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

4. 安定版リポジトリの入手

CPUアーキテクチャで異なるが、基本的にはx86_64/amd64だと思うので、下記で問題ないはず。

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

5. Dockerのインストール

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

6. 動作確認

$ sudo docker run hello-world
$ sudo docker ps -a
hello-worldコンテナが停止していることがわかる
$ sudo docker images
hello-worldイメージを確認できる
$ sudo docker rm コンテナID
コンテナを削除する
コンテナIDはsudo docker ps -aで確認できる
$ sudo docker rmi イメージID
イメージを削除する
イメージIDはsudo docker imagesで確認できる

7. sudoなしでの実行

dockerグループに所属させることで、sudoなしでdockerコマンドを使える。

$ sudo adduser $USER docker
$ newgrp docker

snapでのインストール

1. dockerグループの作成・所属

$ sudo addgroup --system docker
$ sudo adduser $USER docker
$ newgrp docker

2. dockerのインストール

snapではこのとき、docker-composeもインストールされる。

$ sudo snap install docker

3. 動作確認

apt-getでのインストール - 6. 動作確認 と同様。

$ sudo docker run hello-world
$ sudo docker ps -a
hello-worldコンテナが停止していることがわかる
$ sudo docker images
hello-worldイメージを確認できる
$ sudo docker rm コンテナID
コンテナを削除する
コンテナIDはsudo docker ps -aで確認できる
$ sudo docker rmi イメージID
イメージを削除する
イメージIDはsudo docker imagesで確認できる

docker-composeのインストール

snapでインストールした場合は不要。
詳細は下記を参照。https://docs.docker.com/compose/install/

1. docker-composeの入手

最新版であるか、URLを要確認。1.25.3が変わっている恐れがある。

sudo curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

2. docker-composeに実行権を付与

sudo chmod +x /usr/local/bin/docker-compose

3. 動作確認

$ mkdir test
$ cd test
$ vi docker-compose.yml
# 下記をdocker-compose.ymlに書き込む
version: '3'
services:
  test:
    image: hello-world
$ docker-compose up
# 下記のように出力されるはず。
Pulling hello-world (hello-world:)...
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Creating test_hello-world_1 ... done
Attaching to test_hello-world_1
hello-world_1  | 
hello-world_1  | Hello from Docker!
hello-world_1  | This message shows that your installation appears to be working correctly.
hello-world_1  | 
hello-world_1  | To generate this message, Docker took the following steps:
hello-world_1  |  1. The Docker client contacted the Docker daemon.
hello-world_1  |  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
hello-world_1  |     (amd64)
hello-world_1  |  3. The Docker daemon created a new container from that image which runs the
hello-world_1  |     executable that produces the output you are currently reading.
hello-world_1  |  4. The Docker daemon streamed that output to the Docker client, which sent it
hello-world_1  |     to your terminal.
hello-world_1  | 
hello-world_1  | To try something more ambitious, you can run an Ubuntu container with:
hello-world_1  |  $ docker run -it ubuntu bash
hello-world_1  | 
hello-world_1  | Share images, automate workflows, and more with a free Docker ID:
hello-world_1  |  https://hub.docker.com/
hello-world_1  | 
hello-world_1  | For more examples and ideas, visit:
hello-world_1  |  https://docs.docker.com/get-started/
hello-world_1  | 
test_hello-world_1 exited with code 0

snapで動作しない...

ルートディレクトリにディレクトリを作って、docker-compose upすると、docker-compose.ymlを見つけられない...

stack overflowで質問中。
https://ja.stackoverflow.com/questions/63172/snapでdockerをインストールした場合-docker-composeを実行するとdocker-compose-ymlを見つけられない

ERROR: 
        Can't find a suitable configuration file in this directory or any
        parent. Are you in the right directory?

        Supported filenames: docker-compose.yml, docker-compose.yaml
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker for Windowsでdockerの時刻がずれてbuildにコケる問題に対応する

大したことではないのですが、全然情報が出てこなくて大変だったので。
ある日、dockerをbuildしようとすると内部時刻が合わなくてapt-getが失敗してコケるという事態に見舞われました。
※私はdocker内の時刻が3日前になるという具合でした

わかってみると解決策は簡単でした。


Docker Desktopをrestartする!


どうやらWindowsをスリープしていると時刻がずれてくるというバグがあるらしい。
なんだこのバグ…。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-compose.yml → Dockerfile 変数渡し & 複数FROM構成での注意点

docker-compose.yml → Dockerfile に変数を渡す方法

↓この記事で使ったネタです:smiley:
https://qiita.com/yagrush/items/2fbff71c1c2bf12f7d71

1/2 docker-compose.yml側

buildキーの子要素としてargsキーを追加し、
その下に配列として、渡したい変数名と値を書いていきます。

services:
  my-s3access-app:
    build:
      context: ./app
      dockerfile: Dockerfile
      args:
        - GITHUB_ACC=hogehige
        - GITHUB_ACC_PASSWORD=agd82gfo3gfagkaf
     ・
     ・
     ・

2/2 Dockerfile側

ARGコマンドで宣言(キャッチ)すると、それ以降$HOGEで利用可能になります。

FROM golang:1.13
ARG GITHUB_ACC
ARG GITHUB_ACC_PASSWORD
RUN echo -e "machine github.com\nlogin $GITHUB_ACC\npassword $GITHUB_ACC_PASSWORD" > ~/.netrc
RUN go mod download
 ・
 ・
 ・

Dockerfileが複数FROM構成のときの注意点

次のFROMコマンドに処理が移るとき引き継がれないので、ARGしなおさないといけません。

ちなみに複数FROMが必要となるのは
[ソースコードをビルドするイメージ]

[ビルド結果の実行体だけを配備して実行するためのイメージ]
を分けたい時などですね。

FROM golang:1.13 as base

FROM base as builder
ARG GITHUB_ACC
ARG GITHUB_ACC_PASSWORD
RUN echo -e "machine github.com\nlogin $GITHUB_ACC\npassword $GITHUB_ACC_PASSWORD" > ~/.netrc
RUN go mod download
 ・
 ・
 ・
FROM base as scratch
ARG GITHUB_ACC
ARG GITHUB_ACC_PASSWORD
 ・
 ・
 ・
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitLab CI で docker-compose を使う

数時間苦闘したのでメモ。

.gitlab-ci.yml

build:
  stage: build
  image: docker:stable
  services:
    - docker:dind
  script:
    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
    - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG app
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG

test:
  stage: test
  image: tmaier/docker-compose:19.03
  services:
    - docker:dind
  script:
    - docker version
    - docker-compose version
    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
    - sed -i "s|build:|# build:|" docker-compose.yml
    - sed -i "s|context:|# context:|" docker-compose.yml
    - sed -i "s|app_image|$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG|" docker-compose.yml
    - docker-compose -p $CI_COMMIT_SHA config
    - docker-compose -p $CI_COMMIT_SHA pull
    - docker-compose -p $CI_COMMIT_SHA run test
  after_script:
    - docker-compose -p $CI_COMMIT_SHA down -v
    - docker-compose -p $CI_COMMIT_SHA rm -f
  • build ジョブは標準的な手順のまま。1
  • test では
    • image: docker/compose もあったが、 variables を設定してもサーバーとうまく接続できなかったので、 tmaier/docker-compose を使うようにした2。このイメージで直接テストを行うのは難があるので、テストスクリプトを実行して終了するサービス test を追加している。
    • sed: ローカルでは build context で作っているのでそれをコメントアウトしている。イメージは build ジョブで作ったものを使用するようにしている。
    • $CI_COMMIT_SHA: 複数のジョブまたはパイプラインが同時に実行される可能性がある場合は -p project_name で一意にしないとおそらく破綻する。
    • after_script: コンテナとボリュームとネットワークの後始末。

docker-compose.yml

そのまま。
ローカルで test イメージを起動したくないときは docker-compose up -d app などする。

version: "3.0"
services:
  redis:
    image: redis:5.0
    volumes:
      - redis_data:/data

  app:
    build:
      context: app
    image: app_image
    depends_on:
      - redis
    ports:
      - "80:80"
    command: "/app/main.py"

  test:
    image: app_image
    depends_on:
      - app
    volumes:
      - ./:/work:ro
    command: "/work/test.sh"

volumes:
  redis_data:

CI Runner の config.toml

関係する部分を抜粋。

[[runners]]
  name = "xxx"
  url = "xxx"
  token = "xxx"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.docker]
    tls_verify = false
    image = "ubuntu:18.04"
    privileged = true
    volumes = ["/certs/client", "/cache"]

検証環境

CI のログから。

$ docker version
 Client: Docker Engine - Community
  Version:           19.03.5
  API version:       1.40
  Go version:        go1.12.12
  Git commit:        633a0ea838
  Built:             Wed Nov 13 07:22:05 2019
  OS/Arch:           linux/amd64
  Experimental:      false
 Server: Docker Engine - Community
  Engine:
   Version:          19.03.6
   API version:      1.40 (minimum version 1.12)
   Go version:       go1.12.16
   Git commit:       369ce74a3c
   Built:            Thu Feb 13 01:32:22 2020
   OS/Arch:          linux/amd64
   Experimental:     false
  containerd:
   Version:          v1.2.12
   GitCommit:        35bd7a5f69c13e1563af8a93431411cd9ecf5021
  runc:
   Version:          1.0.0-rc10
   GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
  docker-init:
   Version:          0.18.0
   GitCommit:        fec3683
 $ docker-compose version
 docker-compose version 1.25.1, build a82fef0
 docker-py version: 4.1.0
 CPython version: 2.7.16
 OpenSSL version: OpenSSL 1.1.1d  10 Sep 2019
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker メモ

概要

docker を使うたびに毎回ググっていて非効率的なので自分がよく使うものをまとめました。
そのうち内容を追加するかもしれないです。
本記事の任意の内容は暗黙的に (おれだったらこうする) の意を込めているので、参考にされる場合は適宜修正してもらえばと思います。

ベターな方法あるよ〜 / 間違ってるよ〜などあったら教えていただけると助かります。

前提

リモートサーバー上にコンテナを立てて中で機械学習したい。

コンテナ編

コンテナを立てる

コンテナを立てる時にすることは、

  1. コンテナに名前をつける
    • --name $CONTAINER_NAME
  2. マウントするディレクトリを指定する
    • -v $DIR_SERVER:$DIR_CONTAINER
    • マウントするディレクトリが前、コンテナ内にマウントしたディレクトリを配置する場所が後
    • ディレクトリの指定は絶対パスで行う
  3. ポートを指定する
    • -p $PORT_SERVER:$PORT_CONTAINER
    • サーバーのポートが前、コンテナのポートが後

この3つ。なお、これらの操作はコンテナを立てた後には変更できないので、変更したい場合はコンテナを作り直す必要がある。

自分のいつも使っているコマンドはこんな感じ。

docker run --runtime=nvidia -it --privileged -v /home/$USER:/home/$USER -p 6006:6006 -p 8888:8888 --name $CONTAINER_NAME $IMAGE_NAME

① ホームディレクトリをマウントしつつ、② 60068888 のポートを外と繋げる。

ポートを増やしたい or マウントするディレクトリを追加したい

前述の通り、これらの操作はコンテナを立てる時にしか実行できないので、

  1. 新しくイメージからコンテナを立て直す
  2. 現在使用しているコンテナをイメージ化して再びコンテナを立て直す

のどちらかを行う。前者は普通に docker run でOK。
後者は docker commit でコンテナをイメージ化して docker run する。

docker stop $CONTAINER_NAME
docker commit $CONTAINER_NAME $IMAGE_NAME
docker run ...

コンテナに入りたい

バックエンドで起動しているコンテナに入りたい → docker attach $CONTAINER_NAME
終了しているコンテナに入りたい → docker start $CONTAINER_NAMEdocker attach $CONTAINER_NAME

コンテナから抜けたい

バックエンドで起動したまま抜けたい → ctrl + q + p
コンテナ自体を終了させたい → exit

サーバー編

ポート設定

jupyter notebook や tensorboard をブラウザ上で使いたい場合、ローカルとリモートサーバを繋ぐ設定をする必要がある。

  1. ローカルのポートとサーバのポートを繋ぐ
    • ssh -L $PORT_LOCAL:$PORT_SERVER
    • ローカルのポートが前、サーバーのポートが後
    • 踏み台サーバを経由する場合は、踏み台のポートも繋ぐ
    • ex) ssh -L $PORT_ROCAL:$PORT_VIA:$PORT_SERVER
  2. サーバのポートとコンテナのポートを繋ぐ
    • docker run -p $PORT_SERVER:$PORT_CONTAINER

の2つをやればOK。

自分の場合、2. に関しては、サーバの 8888 とコンテナの 8888 を繋いだので、
1. はローカルの 18888 (任意のポート番号) とサーバの 8888 を繋げば、localhost:18888 でコンテナの 8888 にアクセスできる。

ssh $SERVER_NAME -L 18888:8888 -L 16006:6006

ポートを複数繋げたいときは上記のように適宜 -L オプションを増やす。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker Desktop for Mac でApacheのコンテナを立ち上げる

目的

  • Docker Desktop for Mac導入後に確認としてApacheのコンテナを作りブラウザから接続を確認する方法をまとめる
  • とにかくちゃんとDockerが導入できているかの確認なのでディレクトリマウントなどは行わない

実施方法

  1. Docker Desktop for Macの入ったPCで下記コマンドを実行する。

    $ docker run -d -p 8080:80 httpd
    
  2. 下記にアクセスして「It works!」と表示されるか確認する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Docker入門②】『Docker』のセットアップと基本操作

この記事では、《Docker や コンテナ》について、
僕が学習した内容をまとめています。

  • 『Docker』のセットアップ
  • 『Docker』の基本操作

こういった疑問についてまとめています。

※本記事は、自分で学習したことのまとめ用として書いています。
尚、解説で誤った点があれば、スローして頂ければ喜んでキャッチしますのでお願い致します。

<前回のお話>
【Docker入門①】そもそも『Docker』とは…?

(参考)サーバーの準備

assembly-1.jpg

まずは・・・

『Docker』を使用する環境を準備しましょう!

本記事では、詳しく触れませんが…

今回は『CentOS』を前提として、解説していきます。

ですので・・・

VirtualBox』や『VMware』などを利用して、仮想マシンを準備してみて下さい。

※『仮想マシン作成』の記事に関しては、今後まとめる予定です。

(参考)『Docker』のセットアップ

school-2.jpg

yumのリポジトリ設定などを行って、『Docker CE』をインストールしていきます。

Docker CE をインストールするためのリポジトリ設定

ホストOS上に『Docker CE』をインストールする前に、『Docker リポジトリ』のセットアップが必要です。

そのため、まずは・・・

  • yum-utils
  • devicemapper

で必要とされるパッケージをインストールします。

『yum-utils』は、yum-config-managerなどのコマンドが含まれます。

そして・・・

『device-mapper-persistent-data』と『lvm2』は、『devicemapper』の使用に必要です。

devicemapperに関して知りたい方は、下記の記事で丁寧に解説されていますので、参照してみて下さい。
》Dockerのストレージドライバを理解する

$ yum install -y yum-utils device-mapper-persistent-data lvm2

次に・・・

『Docker CE』をインストールするために、『yumリポジトリ』を追加します。

『CentOS 7』では、パッケージ管理ソフトウェアとして『yum』を利用していますが、『Docker』は公式の『yumリポジトリ』を提供していますので、その公式『yumリポジトリ』からインストールすることができます。

そのため・・・

『CentOS 7』に『Docker』の公式『yumリポジトリ』の情報を追加して、リポジトリを使えるようにします。

$ yum-config-manager \
  --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo

下記コマンドで、リポジトリが追加され、有効化されていることを確認しましょう。

$ yum repolist all | grep -i docker

次に・・・

以下のコマンドで『edgeリポジトリ』を無効化します。

【余談】『Docker CE』の『edge』『stable』について

『Docker CE』のDockerエンジンには、頻繁にリリースされる『edge』と約半年ごとに安定版としてリリースされる『stable』2種類あります。

今回は、安定版の『stable』のみを利用ので、『edgeリポジトリ』を無効にします。

$ yum-config-manager --disable docker-ce-edge

パッケージの最新情報を取得します。

$ yum makecache fast

それでは、インストール可能な『Docker』をリストアップしてみましょう。

『edgeリポジトリ』の有効・無効かで表示が異なるので、気になる方は確認してみてください。

$ yum list docker-ce.x86_64  --showduplicates

そして・・・

お待ちかねの『Docker CE』のインストールです。

$ yum install docker-ce

これで『Docker CE』がインストールできました。

ついでに、以下のコマンドでインストールされているか確認しておきましょう。

$ yum list installed | grep docker-ce

再読込し、設定を反映させます。

新規にユニットファイルを作った際や、/etc/systemd/system/配下のファイルを編集した際にリロードします。

$ systemctl daemon-reload

『Docker』を起動します。

$ systemctl start docker

以下のコマンドでサービス自動起動設定をしておくと、マシンの再起動後も自動で『Docker』が起動します。

$ systemctl enable docker

以上で『Docker』のセットアップは終了です。

次は、『Docker』の基本操作について見ていきましょう。

『Docker』の基本操作

manipulation-1.jpg

ここからは、公開されている『Dockerイメージ』を使用し、下記の4つの基本操作について見ていきましょう。

  1. 公開されている『Dockerイメージ』の取得
  2. それを元にコンテナを起動
  3. 起動の確認ができたら、コンテナの停止
  4. 停止したコンテナの削除

STEP①:『Dockerイメージ』の取得

『Dockerイメージ』の一覧を表示

以下のコマンドで、ローカル環境の『Dockerイメージ』の一覧を確認できます。

$ docker images

現状、ヘッダーのみで、何も表示されないと思います。

『Dockerイメージ』のダウンロード

それでは、『Dockerイメージ』を取得してみましょう。

『Dockerイメージ』は、Docker Hubと呼ばれるオンラインサービスが提供されており、そこでイメージの共有やダウンロードが可能です。

Docker Hubからイメージを取得するには、docker pullコマンドを使用します。

docker pullコマンドの書式は、以下の通りです。

$ docker pull NAME[:TAG]
  • NAME:イメージ名
  • TAG:タグ名(省略した場合はlatest)

今回は最新の『Apache httpd』を含んだイメージを取得しますので、コマンドの引数にhttpdを指定します。

$ docker pull httpd

タグ名にはバージョンを指定することが一般的ですが、タグ名を省略した場合はデフォルトでlatestを指定したことになり、最新版がインストールされます。

『Dockerイメージ』の確認

『httpd イメージ』のダウンロードが完了し、イメージに追加されたことを確認するため、docker imagesコマンドを実行します。

$ docker images

『httpd イメージ』が追加されたことが分かるかと思います。

これで『Dockerイメージ』の取得は完了です。

STEP②:コンテナの起動

以下のコマンドでは、ローカル環境のコンテナの一覧を確認できます。

$ docker ps

まだコンテナの起動は行っていないので、ヘッダーのみしか表示されません。

『httpd イメージ』を使ってコンテナを動かしてみる

イメージからコンテナを作成して起動するには、docker runコマンドを実行します。

docker runコマンドの書式は、次の通りです。

$ docker run [OPTION] NAME[:TAG] [COMMAND]
  • OPTION:オプション
  • NAME:Dockerイメージ名
  • TAG:タグ名(省略した場合はlatest)
  • COMMAND:実行時に上書きしたいコマンド

さっそくdocker runコマンドを実行して、コンテナを作成・起動してみましょう。
(コマンドのオプションについては、次で解説します)

$ docker run --name httpd -p 8080:80 -d httpd
オプション 概要
-d コンテナの実行をバックグラウンドで行うオプション。
仮に、このオプションを指定しなかった場合は、ターミナルのコマンド操作がCtrl+Cを実行するまでコンテナに奪われてしまいます。
–name コンテナ名を指定。
(指定しなかった場合は、自動で名前が付けられます)
-p コンテナのポート番号とローカルのコンピュータのポート番号を紐づけるオプション。
今回実行したコンテナは、80番ポートでhttpdが開始されます。 ただし、80番ポートで設定されているのは『コンテナ』であり、『Docker』を実行しているローカルマシンではありません。
そこで、この-pオプションで、『コンテナ』と『ローカルマシン』のポートを紐づけることで、あたかもローカルマシンでhttpdがサービスを提供しているかのような状態を作ることができます。
今回の例では、ローカルマシンの8080番ポートをコンテナの80番ポートに紐づけています。

これで『httpd コンテナ』の実行が完了しましたので・・・

http://localhost:8080

にアクセスしてみてください。

すると・・・

みなさんおなじみの『It work!』が表示されるはずです。

実行中のコンテナを確認する

次に、実行中のコンテナの状態を確認してみましょう。

本記事に沿って操作をしている場合、現時点で『httpd コンテナ』が実行中かと思うので、docker psコマンドで確認してみましょう。

$ docker ps

実行中のコンテナが1つあることが確認できるかと思います。

STEP③:コンテナの停止

実行中のコンテナを停止したい場合は、docker stopコマンドを使用します。

$ docker stop [CONTAINER]
  • CONTAINER:CONTAINER ID(コンテナID)、NAMES(コンテナ名)

コマンドの引数として、『コンテナID』または『コンテナ名』を指定します。

今回は、起動したコンテナに『httpd』という名前を付けたので…

$ docker stop httpd

として、コンテナを停止させます。

停止したコンテナの確認

コンテナを停止したら、同様にdocker psコマンドで停止したかを確認しましょう。

$ docker ps

実行結果にコンテナが表示されなくなったかと思います。

停止させたコンテナも表示させたい場合は…
docker psコマンドに-aオプションをつけて実行します。

$ docker ps -a

表示された結果の『STATUS』欄にExitedと表示されているのが確認できるかと思います。

STEP④:コンテナの削除

停止中のコンテナを削除せずそのままにしておくと、ゴミが残ったままになり、容量の圧迫にもつながるので…

不要になったコンテナは、削除するようにしましょう。

コンテナを削除する場合は、docker rmコマンドを使用します。

$ docker rm [CONTAINER]
  • CONTAINER:CONTAINER ID(コンテナID)、NAMES(コンテナ名)

今回は、起動したコンテナに『httpd』という名前を付けたので…

$ docker rm httpd

として、コンテナを削除します。

削除したコンテナの確認

コンテナを削除したら、同様にdocker ps -aコマンドで削除されたか確認しましょう。

$ docker ps -a

一覧にコンテナが表示されなくなったかと思います。

まとめ

surfing-1.jpg

最後に、今回ご紹介した『Docker コマンド』についてまとめます。

  • イメージのダウンロード:docker pull
  • イメージの一覧の確認:docker images
  • コンテナの実行:docker run
  • コンテナの一覧確認:docker psdocker ps -a
  • コンテナの削除:docker rm
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む