- 投稿日:2020-09-09T23:51:53+09:00
DockerでのRails環境構築(個人的黙示録)
Dockerfileの作成
-# ビルドコンテキスト % mkdir product-register % cd product-register -# GemfileとGemfile.lockの作成 % touch Gemfile Gemfile.lock -# Gemfileの編集 % vim Gemfileproduct-register/Gemfilesource 'https://rubygems.org' gem 'rails', '~>5.2'-# Dockerfileの編集 % vim Dockerfile
product-register/DockerfileFROM ruby:2.5 RUN apt-get update && apt-get install -y && \ buile-essential \ libpq-dev \ nodejs \ postgresql-client \ yarn WORKDIR /product-register COPY Gemfile Gemfile.lock /product-register/ RUN bundle install-# コンテナの作成 % docker build .
docker-compose.ymlの記述
-# docker-compose.ymlの編集 % vim docker-compose.yml
docker-compose.ymlversion: '3' services: web: build: . ports: - '3000:3000' volumes: - '.:/product-register' tty: true stdin_open: true-# コンテナの立ち上げ % docker-compose up -d -# コンテナ内に入って作業をする場合 % docker-compose exec web bashRailsのセットアップ
-# アプリの作成、DBの設定、bundleはDockerfileで行うので—skip # rails new . —force —database=postgresql —skip-bundle -# ホスト側でGemfileの内容が変わっていることを確認する % cat Gemfile -# bundle installする必要があるので一度停止する # exit $ docker-compose down -# docker-compose upをすると前のイメージが使われるので再度buildを行う $ docker-compose up —build -d % docker-compose exec web bash -# railsのサーバを起動 $ rails s -b 0.0.0.0localhost:3000で接続できるがDBの設定を行っていないのでエラーページとなる。
DBのセットアップ
config/database.ymldefault: &default adapter: postgresql encoding: unicode host: db user: postgres port: 5432 password: <%= ENV.fetch("DATABASE_PASSWORD") %> # For details on connection pooling, see Rails configuration guide # http://guides.rubyonrails.org/configuring.html#database-pooling pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>Passwordはセキュリティ的に直接書くのは望ましくないので環境変数で呼び出すようにする。
docker-compose.ymlの変更
docker-compose.ymlversion: '3' # dockervolumeここにデータが保存される volumes: db-data: services: web: build: . ports: - '3000:3000' volumes: - '.:/product-register' # コンテナの環境変数設定、本来は直接パスワードを書いてはいけない。 environment: - 'DATABASE_PASSWORD=postgres' tty: true stdin_open: true # dbサービスが作られたら作成される depends_on: - db # webからdbにアクセスできる links: - db # postgresのコンテナ db: image: postgres # ホストのdb-dataにデータを保管 volumes: - 'db-data:/var/lib/postgresql/data' environment: - 'POSTGRES_USER=postgres' - 'POSTGRES_PASSWORD=postgres'docker-composeで起動
% docker-compose up -d -# 2つのサービスが起動しているのが確認できる Creating product-register_db_1 ... done Recreating product-register_web_1 ... done % docker-compose exec web bash -# DBの作成 # rails db:create Created database 'product-register_development' Created database 'product-register_test'データベースが作られているのが確認できる。
ここからRailsのアプリを作成することができる。アプリを作り動作を確認する
-# scaffoldで簡単なアプリを作る # rails g scaffold product name:string price:integer vender:string -# 作成したテーブルを定義する # rails db:migrate -# サーバを立ち上げる # rails s -b 0.0.0.0localhost:3000で接続でき、railsのページが表示されていることが確認できる。
localhost:3000/productsで作られたアプリに接続できる。
- 投稿日:2020-09-09T22:52:48+09:00
Docker上にvue.jsの開発環境する。docker-composeで簡単に作成する手順。
Docker上にvue.jsの開発環境する。docker-composeで簡単に作成する手順。
dockerを使ってvue.jsの開発環境を簡単に構築できるようにする。
本番に応用できるよう、DockerfileのENTRYPOINTでコンテナ内のスクリプトを実行する。
また、実行はdocker-composeを使用する。
実行順序は docker-composeファイル -> Dockerファイル -> スクリプトファイル となる。複数人のプロジェクトを想定して、作成したファイル群をgithubにアップして、cloneしvue.jsの開発環境を立ち上げるまで。
開発手順
- Dcokerのインストール
- Dockerfileの作成
- シェルスクリプトの作成
- docker-compose.ymlの作成
- .dockerignoreの作成
- aliasの作成
- aliasファイルの読み込み
- docker-composeの実行
- コンテナ内に入る
- vueの開発環境を作成する
- ファイルの移動と削除
- vue開発環境の確認
- githubに作成したファイル群をプッシュ
- 他のプロジェクトメンバーのローカルで実行する
Dcokerのインストール
Dockerの公式ページからOSに合ったDockerをインストール
https://docs.docker.com/get-docker/
設定が完了したら、正しくインストールされているかターミナルで確認。
$docker -v Docker version 19.03.12 $docker-compose -v docker-compose version 1.26.2dockerとdocker-composeのバージョンがそれぞれ表示されたらOK。
Dockerfileの作成
環境開発時のコマンドはdocker-composeで実行するが、独自のイメージを作成(build)する際に、Dockerfileを指定する。
Dockerfileはコンテナ内の処理となる。
プロジェクトフォルダを作成したい階層に移動。
ここでは、PJのルートディレクトリとしてvuecliを作成する。ターミナル#vuecliフォルダを作成し移動 $ mkdir vuecli && cd vuecli #Dockerfileを作成 $ touch Dockerfile #vimエディタでファイルを開く $ vi Dockerfile▼vimエディタの超基本コマンド
- 貼り付け:
p
- インサートモード:
i
- インサートモード終了:
esc
- 保存して終了:
:wq
▼Dockerファイルの内容
Dockerfileは拡張子不要。
Dockerfileには下記を記述。Dockerfile#nodeイメージをpullする FROM node:10.15.3-alpine #working directory WORKDIR /app #vuecliインストール RUN npm install -g @vue/cli #shファイルをコンテナにコピー COPY ./scripts/docker.start.sh /scripts/start.sh #shフォルダの権限追加(全員実行可) RUN chmod +x /scripts/* #初期実行 # ENTRYPOINT [ "/scripts/start.sh" ]Dockerfileはイメージを作成するための元となるファイル。
・
FROM イメージ名:タグ
継承のような機能。指定したイメージを取得し、以下に続く処理を実行する。
タグはバージョンを指定。記載しない場合は最新版(latest)が選択される。
イメージの取得は、まずdocker公式の共有イメージ置き場であるdockerhubで該当するものがあるか探す。ない場合はローカルのDocker内のイメージを探す。
(補足) node:10.15.3-alpineとは?
本当はvue-cliのイメージを取得したいが、現状dockerhubにはないため、nodeのイメージを取得する。バージョンは10.15.3、OSはlinux alpineを選択。
linux alpineは軽量のOS。dockerのイメージで見かけることが多い。注意点としてはbashファイルが存在せず、shファイルのみとなること。(後々の記述に影響)
・
WORKDIR パス
コンテナ内のワーキングディレクトリの指定。
デフォルトではルートディレクトリ(/)が指定されているが、WORKDIRで変更することができる。
・
RUN コマンド
コンテナ内で実行するコマンドを記述。
「npm install -g @vue/cli」で、vueを操作するコマンドラインインターフェース(cli)をインストールする。exec形式(配列でコマンドと引数を順に記述)での記述も可能。例えば上のコマンドだと、
RUN ["npm", "install", "-g", "@vue/cli"]
・
COPY ホスト内パス コンテナ内パス
ホスト内のファイルをコンテナの指定したパスにコピーする。
親フォルダが存在しない場合は自動で作成される。コンテナ内のシェルスクリプトでコマンドを実行する仕様とするため、予めホスト内でコマンドを記述したシェルスクリプトを作成しておき、それをコンテナ内にコピーする。(シェルファイルの作成は後ほど)
シェルスクリプトに実行権限を与え、ファイルパス指定で実行できるようにする。
「RUN chmod +x /scripts/*」で権限を付与。実行権限を与えない場合は、shコマンドでないと実行できない。「$sh シェルスクリプトパス」
・
ENTRYPOINT [ "コマンド", "引数",,]
ENTYPOINTはコンテナ初回起動時に実行するコマンド。
コンテナ内のスクリプトファイルのパスを指定することで、コンテナ初回起動時に指定したスクリプトを実行できる。
(補足)
ENTRYPOINT
とCMD
の違い
ENTRYPOINT
とCMD
はどちらもコンテナ初回実行時に実行するコマンド。どちらか一つは必ず必要で、記述がないとエラーになる。
ENTRYPOINTとCMDもexec形式(配列のような形)でコマンドを渡せる。その際、引数の扱いが異なる。
- ENTRYPOINT: 引数の変更はできない。追加の引数として処理する。
- CMD: 引数に変数を指定できる(状況に合わせて変更可能)
コマンドの記述でよく見る例
CMD [ "/bin/sh" ]
: shファイルを実行CMD [ "/bin/bash" ]
: bashファイルを実行CMD [ "npm", "run", "serve" ]
: 「$npm run serve」コマンドを実行(vue.jsのサーバー起動)
シェルスクリプトの作成
ローカルのPJルートディレクトリにscriptsフォルダを作成し、シェルスクリプト「docker.start.sh」を作成する。
ターミナル#scriptsフォルダとシェルファイルを作成 $mkdir scripts && touch ./scripts/docker.start.sh #vimエディタで開く $vi ./scripts/docker.start.sh▼シェルスクリプトの記述内容
docker.start.sh#!/bin/sh #node_modulesインストール echo "npm install" npm install #vue起動 echo "npm run serve. " npm run serve #メモを出力 echo "localhost:18080"※(補足)シェルスクリプトの利用について
指定のシェルスクリプトを使用せず、DockerfileのみでCMD ["npm","run","serve"]
でも実行できるが、実際の開発で、開発環境と本番環境でインストールするライブラリを変更するなど、条件分岐(if)などを使うことを想定。
docker-compose.ymlの作成
docker-composeは複数のコンテナでプロジェクトを立ち上げる時に使う。
例えば、①ruby on rails, ②PostgreSQL, ③Redis, ④Sideqikのコンテナをまとめて立ち上げることができる。
docker-composeで立ち上げたコンテナは自動で独自のネットワーク(コンテナ同士の関連づけ)が設定される。
docker-composeファイルの拡張子はyml(ヤムル)なので、ヤムルの仕様に沿って記述する。
まずはPJのルートディレクトリにファイルを作成する。
terminal#ファイル作成 $touch docker-compose.yml #vimエディタで開く $vi docker-compose.yml▼docker-compose.ymlの記述内容
docker-compose.yml#docker-composeのバージョンを指定 version: "3.7" volumes: #volumeはホストにコピー or 表示させないもの ##バイナリファイル(node_module)など、OS依存があるもの #node_moduleを入れるvolume vue-cli-node-volume: services: #コンテナ詳細 app: image: vuecli:1 build: context: . dockerfile: Dockerfile container_name: vuecli3 ports: - "18082:8080" volumes: #node_moduleを入れるボリューム - vue-cli-node-volume:/app/node_modules #コンテナ内の指定ディレクトリをホスト側と同期 - .:/app/ #-it stdin_open: true tty: true・
version:"メジャーNo.マイナーNo"
docker-composeのファイルフォーマットのバージョンを指定する。versionにより記述方法に違いがあるため注意。今回は3.7を指定。
マイナーNoを記述しない場合、0に置き換わる。
例: version:"3" = version:"3.0">ファイルフォーマットとdocker-composeのバージョンの対応表
https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/compose-versioning/・
volumes:
トップレベルに「volumes:」を記述すると、指定したvolume名を各コンテナで共有できるようになる。
volumeを使用すると、指定したコンテナのディレクトリやファイルをホストのdockerのストレージに保存する。
▼volumeの使い方
volumeの使い方は大きく3つ。
(1)ホスト側のPJルートディレクトリと同期する
コンテナ内のワーキングディレクトリと、PJのルートディレクトリを同期することで、viewファイルやsrcなどがリアルタイムで同期できる。
- .:/app/
(ホスト側のパス:コンテナ側のパス)
上記例では、コンテナのワーキングディレクトリ/app/を、ホスト側のdocker-composeを実行するディレクトリに同期している。(2)ホスト側にコピーしたくないファイルやディレクトリの指定。
volume名を指定することで、.dockerignoreファイルと組み合わせ、ホスト側に同期させないようにすることができる。
例えば、バイナリファイルが該当する。
バイナリファイルはバイナリ(0,1)で書かれたPC用のテキストファイルでOS毎に内容が異なる(依存性がある)。コンテナ内にインストールしたnodeはLinux用なので、ホスト側のOSと一致しない場合に不具合を起こす。なので、nodeの入ったnode_modulesはホスト側のPJディレクトに同期させないようにする。(.dockerignoreファイルと合わせて使う)
(3) 同期除外しなくてもいいが、ホスト側にも特に必要ないファイルやディレクトリ
ログファイルなどログ分析用ファイルに同期している場合はホストのPJディレクトリに同期する必要はない。
volumeの記述方法
volumesの記述は
ホスト側:コンテナ側
。
実際の記述方法は大きく3つ。(1)コンテナ側のパスのみ
./logs
/var/lib/mysql
ホスト側のパスを記述しない場合、コンテナ内の指定したフォルダはホストのvolume内のどこかに保存される。
呼び出す必要もないファイルやディレクトリに使う。
(2) ボリューム名で指定
node_volume: ./node_modules
ホスト側をボリューム名で記述する方法。この場合、docker内に指定したボリューム名のディレクトリが作成され、その中に指定したフォルダやファイルが保存される。
ホスト側のPJディレクトリに保存したくない場合に使用。(.dockerignoreを合わせて使う)
(3) パスで指定
./cache:/tmp/cache
パスで指定することも可能。
上記例では、ホスト側を相対パス、コンテナ側を絶対パスで指定。・
sevices:
コンテナと使用するイメージを設定する。
今回はappコンテナのみ作成。・
image: イメージ名:タグ
コンテナ作成のために使用するimageを指定する。
タグはバージョン。記述しない場合はlatestとなる。buildがある場合は、buildに記載の内容からイメージを作成する。buildの指定がない場合は、dockerhub、ローカルの順にイメージを探す。
・
build
イメージを作成するためのDockerfileを指定する。
記述方法は2つ。(1)Dockerファイルのパスとファイル名で指定
build: context: Dockerファイルのパス dockerfile: ファイル名(補足)Dockerfileのファイル名について
Dockerfileのファイル名は「Dockerfile」に限定する必要はない。指定ディレクトリの拡張子のないファイルを構築用ファイルとみなす。
誰が見てもわかりやすいように「Dokerfile」を記述するのが一般的。
▼ファイル名の例
- Dockerfile
- Dev.Dockerfile
- Dockerfile-2(2)ファイルのパスで指定
構築用ファイル(拡張子のないファイル)がディレクトリに1つのみのとき、ディレクトリパスのみの指定もできる。build: Dockerファイルのパス・
container_name:
作成したコンテナの名前を指定する。
「docker ps -a」 でコンテナの一覧を出した時に表示される名前。・
ports: - ホスト側:コンテナ側'
ポートの指定。複数設定することも可能。
「- "18082:8080"」の場合、コンテナ側の通信ポート8080と、ホスト側の18082ポートをつなげる。
ホスト側のブラウザにlocalhost:18082と打ち込むと、コンテナ内で開発用サーバーを立ち上げた時に表示されるlocalhost:8080に接続する。
・
stdin_open: true
コンテナ起動時のオプション。標準入力(standard in)を許可する。
コンテナ内のOSとbash(sh)を通してコマンド入力する場合に必要。Dockerのコマンドでは「-i」
・
tty: true
コンテナ起動時のオプション。標準出力用の擬似ターミナルを起動する。
コンテナ内のOSとbash(sh)を通してコマンド入力する場合に必要。Dockerのコマンドでは「-t」
基本的に「-t」と「-i」はセット(-it)で使う。
.dockerignoreの作成
ホスト側に同期したくないファイルやディレクトリのパスを記述する。(.gitignoreと同じ機能)
terminal#ファイルの作成 touch .dockerignore #vimエディタで開く vi .dockerignore▼.dockerignoreの内容
.dockerignore#node_modulesは同期しない node_modulesコンテナ作成を実行すると、ローカル内にnode_modulesという空のフォルダが自動作成される。コンテナ内の同じフォルダの内容を同期しなくなる。
aliasの作成
ここまでで、ようやくイメージとコンテナを作成するために必要なファイルが揃った。
- docker-compose.yml
- Dockerfile
- docker.start.sh
- .dockerignore
この時点でdocker-composeを実行することもできるが、本番を見据えてdocker-composeコマンドのaliasを作成することで、より簡単に操作できるようにする。
作成の流れは、aliases.shファイルを作成しコマンドを記述。bash_profileでファイルを読み込み、bash_profileをリロード。
terminal#ファイルを作成 $ touch aliases.sh #vimエディタで開く $ vi aliases.sh▼aliases.shの内容
aliases.sh#イメージの作成とコンテナ起動 alias vue-pj="docker-compose up --build app" #コンテナ内のshファイルを起動 alias vue-exec="docker exec -it vuecli sh"・
alias ショートカットコマンド="本来のコマンド
イコールの前後にスペースがあるとエラーになる。・
docker-compose up --build app
「docker-compose up [サービス名]」:指定したサービスの内容を実行。イメージがない場合はビルドし、コンテナを起動する。イメージが既に存在する場合は上書きせず、それを使用する。
docker-compose.ymlの変更内容を反映したいため、「--build」オプションをつけることで、イメージが存在しても再度イメージを構築する。(docker-compose build && docker-compose up appと同じ)
▼サービス名の指定がない場合
サービス名を指定しない場合は、記述してある全てのコンテナを起動する。今回の環境では、appの指定がなくても同じ挙動となるが、実際は開発環境や本番環境で立ち上げるコンテナを切り替えることがあるためあえて指定。
▼「-d」オプション
-dオプションをつけると、バックグラウンドモードでの起動となり、bash(or sh)が起動しない状態となる。
コンテナ内の実行内容が見えなくなってしまうため、今回は付けない。・
docker exec -it コンテナ名 sh
指定したコンテナのシェルを立ち上げる。コンテナ内がbashの場合はshではなくbashを指定。今回はlinux alpineのためshを指定。
aliasファイルの読み込み
作成したaliasが使えるように、bashで読み込む。
terminal#bash_profileをvimエディタで開く $ vi ~/.bash_profile▼bash_profileの内容
bash_profile#作成したファイルを読み込み(フルパスで記述) source /Users/.../vuecli/aliases.shterminal#bash_profileのリロード $ source ~/.bash_profile #aliasの確認 $ alias alias vue-exec='docker exec -it vuecli sh' alias vue-pj='docker-compose up --build app'作成したaliasが表示されていればOK。
bash_profileとは?
bash_profileはシェルをbashで起動したときに読み込まれるファイル。
設定したaliasはシェルを閉じると消えるが、bash_profileに記述することで毎回自動でロードされる。
似たファイルで、より高頻度でロードする、.bashrcというのもある。
docker-composeの実行
いよいよdocker-composeを実行し、イメージとコンテナを作成する。
docker-compose.ymlのあるディレクトリで先ほど設定したコマンドを実行。
terminalvue-pjこれで、コンテナ内にnode.jsとvue-cliがインストールされる。
コンテナ内に入る
コンテナ内でvue-cliを使ってvue.jsの開発環境を作成するため、先ほど作成したaliasでコンテナないのシェルを起動する。
terminalvue-exec /app #
/app #
と表示されれば、docker内に作成したワーキングディレクトリでコマンドを打ち込める状態になっている。
vueの開発環境を作成する
コンテナ内シェル/app #vue create -d pj
vue create プロジェクト名
ここではプロジェクト名をPJとして実行。
オプションの「-d」はデフォルト設定(bavelとeslint)で作成。「-d」を記述せず、vue-cliの対話モードでオプションを選択してくこともできる。
ファイルの移動と削除
vue createを実行するとフォルダは指定したプロジェクト名のフォルダの中に作成される。
ホスト側のプロジェクトファイルのルートディレクトリとコンテナ内のワークディレクトリを同期させたいため、コンテナ内のプロジェクトフォルダの中身を一階層上に上げる。
.dockerignoreに記述しているnode_modulesは同期するディレクトリに移動できないため、一度削除し再インストールする。
まず、コンテナ内のvue-cliが立ち上がっているので、
ctrl + c
でいったん終了し、コンテナ内のシェルに戻る。コンテナ内シェル#pjフォルダを一階層上に移動(隠しファイル含む) ##gitignoreのnode_moduelsは移動できない mv -f ./pj/* ./pj/.* . <br> ##node_modulesファイルを削除し、再インストール rm -r pj && npm install ##yarn関連ファイルを削除。 rm *yarn* ##コンテナ内を確認 /app # ls Dockerfile node_modules scripts aliases.sh package-lock.json src babel.config.js package.json docker-compose.yml publicホスト側にコンテナ内のファイルが反映されていればOK
vue開発環境の確認
これで自分のPCでの開発環境の設定が完了したので、実際にWEBページが開けるか確認する。
npm run serve
でサーバーを再起動できるが、dockerの練習も兼ね一旦コンテナから出て確認してみる。#コンテナから抜ける /app # exit #起動中のコンテナを確認 $docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ebe0276cb7f0 vuecli:0 "/scripts/start.sh" 36 minutes ago Up 4 minutes 0.0.0.0:18080->8080/tcp vuecli#イメージを確認 $docker images REPOSITORY TAG IMAGE ID CREATED SIZE vuecli 0 c6a23f947246 32 hours ago 338MB #イメージの詳細 $docker image inspect vuecli:0docker-compose.ymlに記述したコンテナ名とイメージ名のコンテナとイメージがそれぞれ存在していることがわかる。
WEBページを確認するため、再びコンテナ内に入る。
#コンテナ内に入る $vue-exec #サーバーを起動 /app # npm run serve App running at: - Local: http://localhost:8080/ It seems you are running Vue CLI inside a container. Access the dev server via http://localhost:<your container's external mapped port>/上記が表示されればサーバーの起動完了。
WEBブラウザでページを表示する。
docker-composer.ymlで設定したホスト側のポートを入力。
localhost:18080
WEBページが表示されれば成功。
githubに作成したファイル群をプッシュ
このままでは自分しか使えないため、複数人で開発を進められるようgithubのリモートレポジトリに作成したファイル群をプッシュする。
githubのレポジトリを指定してアップする。
git init git commit -m "first commit" git branch -M master git remote add origin https://github.com/(レポジトリのフルパス) git push -u origin master
他のプロジェクトメンバーのローカルで実行する
前提条件として、dockerとdocker-composeが入っていること。
#リモートレポジトリをclone ##クローンした際のフォルダ名をvuecli(任意)としている。 $git clone https://github.com/(レポジトリのフルパス) vuecli #フォルダ移動 $cd vueclialiasファイルの読み込み
作成したaliasが使えるように、bashで読み込む。
terminal#bash_profileをvimエディタで開く $vi ~/.bash_profile▼bash_profileに以下を記述
bash_profile#作成したファイルを読み込み(フルパスで記述) source /Users/.../vuecli/aliases.shterminal#bash_profileのリロード $source ~/.bash_profile #aliasの確認 $ alias alias vue-exec='docker exec -it vuecli sh' alias vue-pj='docker-compose up --build app' #イメージとコンテナ作成 $vue-pj 省略 App running at: - Local: http://localhost:8080/ It seems you are running Vue CLI inside a container. Access the dev server via http://localhost:<your container's external mapped port>/上記が表示されればサーバーの起動完了。
WEBブラウザでページを表示する。
docker-composer.ymlで設定したホスト側のポートを入力。
localhost:18080
WEBページが表示されれば成功。
以上。
- 投稿日:2020-09-09T21:10:37+09:00
DockerでFirebase Local Emulator Suiteを起動する。
はじめに
Firebase Local Emulator Suiteはローカル環境でFirestoreやCloud FunctionsといったFirebaseプロジェクトのコンポーネントをエミュレートできる環境です。
https://firebase.google.com/docs/emulator-suite?hl=ja本記事ではDocker及びDocker Composeを利用して上記の環境を構築したいと思います。
開発環境
- macOS Catalina 10.15.6
- Docker Desktop stable 2.3.0.4
なお、本記事で使用したコードはこちらです。
実際に作ってみる。
はじめにFirebaseのプロジェクトを作成しておきましょう。
https://console.firebase.google.com/
後述するEmulator Suite UI(GUI上でエミュレータを管理できるコンソール)を利用するために必要となります。
使用するプロジェクトのIDは.envファイルに控えておきます。$ mkdir empty_dir && cd empty_dir $ touch .env.envGCP_PROJECT_ID=YOUR_PROJECT_IDそれでは早速Dockerfileから作成していきます。
エミュレータの動作要件を満たすようイメージを作成します。
https://firebase.google.com/docs/emulator-suite/install_and_configure?hl=ja$ mkdir docker $ touch ./docker/firebase.dockerfiledocker/firebase.dockerfileFROM ubuntu:20.04 RUN apt-get update -y RUN apt-get install -y curl openjdk-11-jre-headless RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - \ && apt-get install -y nodejs RUN npm install -g firebase-toolsつづいてDocker Composeの構成ファイルを作成します。
ボリュームのマウントも行うため適宜ディレクトリも作成しておきます。$ mkdir firebase $ touch docker-compose.yamldocker-compose.yamlversion: "3" networks: backend: services: workspace: image: golang:1.15 environment: FIRESTORE_EMULATOR_HOST: "firebase:8080" GCP_PROJECT_ID: "${GCP_PROJECT_ID}" volumes: - ./gopath/:/go:cached - ./workspace/:/opt/workspace:cached ports: - 8000:8000 working_dir: /opt/workspace networks: - backend command: bash tty: true firebase: build: context: ./docker dockerfile: firebase.dockerfile volumes: - ./firebase/emulators/:/opt/workspace:cached - ./firebase/bin/:/root/.cache:cached - ./firebase/config/:/root/.config:cached ports: - 4000:4000 # Emulator Suite UI - 5000:5000 # Firebase Hosting - 5001:5001 # Clound Functions - 9000:9000 # Realtime Database - 8080:8080 # Cloud Firestore - 8085:8085 # Cloud Pub/Sub working_dir: /opt/workspace networks: - backend command: bash tty: true今回はGo言語からFirestoreのAPIを叩いてみたいと思います。
./workspace/go.modmodule github.com/kyhei/firebase_emu_sample go 1.15 require ( cloud.google.com/go/firestore v1.3.0 golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f // indirect golang.org/x/tools v0.0.0-20200904185747-39188db58858 // indirect google.golang.org/api v0.31.0 // indirect google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d // indirect )./workspace/main.gopackage main import ( "context" "log" "os" "cloud.google.com/go/firestore" ) func main() { ctx := context.Background() client, err := firestore.NewClient(ctx, os.Getenv("GCP_PROJECT_ID")) defer client.Close() if err != nil { log.Fatal(err.Error()) } doc, _, err := client.Collection("users").Add(ctx, map[string]interface{}{ "name": "kyhei", "age": 123, }) if err != nil { log.Fatal(err.Error()) } log.Println(doc.ID) q := client.Collection("users").Select("name", "age") docs, err := q.Documents(ctx).GetAll() if err != nil { log.Fatal(err.Error()) } for _, doc := range docs { log.Println(doc.Data()) } }ここまでの内容でDocker Composeを実行してみましょう。
$ docker-compose up -d $ docker-compose ps2つのコンテナが起動していればOKです。
エミュレータの起動と設定
firebaseコンテナにログインし、Firebaseプロジェクトの初期化を行います。
$ docker-compose exec firebase bash root@da35c7925947:/opt/workspace# firebase login --no-localhost root@da35c7925947:/opt/workspace# firebase init
firebase init
では、プロジェクトを既存のものを選択し、
利用サービスの選択肢では、Emulatorsを選びます。(他はなんでもOKです。)
Emulators Setup
では全てのエミュレータにチェックを入れましょう!
その後それぞれに関する設定が聞かれますが全てデフォルトで大丈夫です。初期化が完了したら、
firebase.json
を編集します。./firebase/emulators/firebase.json{ "emulators": { "functions": { "host": "0.0.0.0", "port": 5001 }, "firestore": { "host": "0.0.0.0", "port": 8080 }, "database": { "host": "0.0.0.0", "port": 9000 }, "hosting": { "host": "0.0.0.0", "port": 5000 }, "pubsub": { "host": "0.0.0.0", "port": 8085 }, "ui": { "enabled": true, "host": "0.0.0.0", "port": 4000 } } }それでは次のコマンドで実際にエミュレータを起動しましょう。
root@da35c7925947:/opt/workspace# firebase emulators:start初回は実行ファイルがダウンロードされます。
エミュレータが立ち上がったらhttp://localhost:4000でコンソールにアクセスできればOKです!Firestoreエミュレータの確認
前項で作成したスクリプトを実行して、Firestoreへの接続を確認してみましょう。
$ docker-compose exec workspace bash root@c64fed9c2890:/opt/workspace# go run main.go 2020/09/09 07:17:08 6WQVScx2NGm4oli8f7iw 2020/09/09 07:17:08 map[age:123 name:kyhei]コンソールを確認すると無事ドキュメントが追加されているのが確認できます。
お疲れ様でした!
Cloud FunctionsやHostingを起動するためにはそれぞれの初期化が必要となります。
エミュレータ起動時のログから初期化のコマンド等が指示されますので、そちらを実行していけばOKです。
- 投稿日:2020-09-09T20:34:13+09:00
Dockerでflask+Herokuのための環境構築からデプロイまで
はじめに
およそ1年前にDjangoを使って簡単なWebアプリを開発した。
データ収集からAI開発、Webアプリ公開まで全てPythonで済ませた話
入力されたURLからスクレイピングでデータ取得→学習済み機械学習モデルで推論→答えを返す
という非常にシンプルなものである。アプリはこちら↓
キー判別AI久しぶりに使ってみたところ、スクレイピング先のサイトの仕様変更により、正しい結果を得られなくなってしまった。これはマズイと思い改修することにした。
久しぶりにコードを覗いてみたが、自分でもよくわからない…開発当時はとにかく動かすことを目標にしていたこともあり、コードも汚いし、デプロイ方法もすっかり分からなくなっている…
というわけで、今後も不定期的に改修することを考え、開発やデプロイをしやすくするためにDockerでの環境構築を実施した。クローンしてdocker-composeすれば開発できて、なおかつコンテナからherokuにデプロイできるようにするのを目標とする。
また、このアプリ自体がDBも使わず非常にシンプルなので、明らかにDjangoを使う必要もないので、この機会にflaskに書き換えちゃいます。
Githubにコードを公開しています。
https://github.com/hatena-hanata/KJA_appディレクトリ構造
最終的なディレクトリ構造はこちらです。
KJA_APP ├── Dockerfile ├── Procfile ├── app.py ├── docker-compose.yml ├── requirements.txt └── src ├── modules │ ├── module.py │ └── music_class.py ├── static │ └── model │ ├── le.pkl │ └── model.pkl └── templates環境構築
docker-compose.ymlversion: '3' services: web: build: . ports: - "8080:8080" volumes: - .:/home/KJA_APP tty: true environment: TZ: Asia/Tokyo command: flask run --host 0.0.0.0 --port 8080DockerfileFROM python:3.8.0 USER root # install google chrome RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' RUN apt-get -y update && apt-get install -y google-chrome-stable && apt-get install -yqq unzip # install chromedriver RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/ # install heroku cli RUN curl https://cli-assets.heroku.com/install.sh | sh # set display port to avoid crash ENV DISPLAY=:99 # upgrade pip RUN apt-get update && apt-get install -y \ && pip install --upgrade pip # change dir WORKDIR /home/KJA_APP # install module COPY requirements.txt /home RUN pip install -r /home/requirements.txt # flask setting ENV FLASK_APP '/home/KJA_APP/app.py' ENV FLASK_DEBUG 1今回、seleniumでchromeを動かしてスクレイピングするため、最初にchromeとchrome driverをインストールしています。こちらのdockerfileを参考にしました。
また、herokuへのデプロイのために、heroku cliもインストールしています。最後の2行flask settingでは、flaskに関する設定を行っています。
FLASK_APP
では、flaskのメイン関数のあるpyファイルを指定することで、flask run
コマンドでそのファイルが実行されるようになります。
FLASK_DEBUG
を1にすることでデバッグモードになり、ファイルの更新がリアルタイムで反映されるようになります。これにて、git clone→docker-composeですぐに開発ができるようになりました。docker-composeの際に
flask run
コマンドを実行しているので、http://localhost:8080/
にアクセスすればアプリが走っていることが分かります。
Herokuにデプロイ
Herokuへの会員登録は済ませているものとします。
準備
- requirements.txt
必要なライブラリをrequirements.txtに書き込みます。デプロイのためにgunicorn
が必要なので、pipで忘れずにインストールしておきましょう。- Procfile
プロジェクト直下に作成します。以下のように書きます。
左のappがプロジェクト直下のapp.pyのことで、右のappはapp.pyで定義したFlaskインスタンスの変数名?です。 ちょっと何言ってるか分かりづらいと思うので、こちらを読んでください。
https://stackoverflow.com/questions/19352923/gunicorn-causing-errors-in-herokuProcfileweb: gunicorn app:app --log-file -アプリ作成
ターミナルからでもできますが、ブラウザからの方が分かりやすいので、ブラウザでやります。
- ブラウザからHerokuにログイン
https://id.heroku.com/login- New -> Create new app でアプリを作成
適当に名前をつけます。- ビルドパックの追加
今回のアプリがpythonであることを明示するために、作成したアプリのページで Settings -> Buildpacks からheroku/python
を追加します。 (デプロイ時に自動でpythonを追加してくれる場合もあるそうですが、自分のディレクトリ構造が悪かったせいか、pythonプロジェクトと認識されず困ったので、予め手動で追加しておくことをオススメします。)
また、今回はseleniumとchromeを利用したスクレイピングをするため、chromeとchrome driverが必要になります。これもビルドパックの追加で対応できます。
https://qiita.com/nsuhara/items/76ae132734b7e2b352dd#chrome%E3%81%A8driver%E3%81%AE%E8%A8%AD%E5%AE%9Aデプロイ
ここからはDockerのコンテナに入ってデプロイします。
1. herokuにログイン
リンクが出てくると思うので、それをクリックして認証する。root@a59194fe1893:/home/KJA_APP# heroku login
- herokuのアプリ用リポジトリにpushする。 urlは
https://git.heroku.com/[上の2.で作成したアプリ名].git
です。(ブラウザのSettingsでも確認できます)。
下のコマンドは、今のブランチの内容をherokuのリポジトリのmasterブランチにpushする、という意味です。root@a59194fe1893:/home/KJA_APP# git push https://git.heroku.com/[上の2.で作成したアプリ名].git masterエラーがでなければこれにてデプロイ完了となります。
最後に
docker-compose便利ですね。
- 投稿日:2020-09-09T19:52:24+09:00
【MySQL】dockerで構築したデータベースサーバが日本語対応していないかも、、、
環境
$ docker -v Docker version 19.03.12 $ rails -v Rails 6.0.3.2 $ mysql --version mysql Ver 14.14 Distrib 5.7.29, for osx10.15 (x86_64) using EditLine wrapperデータベースに日本語でユーザー名を登録しようとすると、、、、
エラー内容ActiveRecord::StatementInvalid (Mysql2::Error: Incorrect string value: '\xE3\x83\x8F\xE3\x83\xAA...' for column 'name' at row 1):あらら、日本語として認識されてない模様
ここは、データベースのcharasetでも見て設定確認しますか。$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f51c4b953b05 feeder-in_back "rails server -b 0.0…" About an hour ago Up About an hour 0.0.0.0:3000->3000/tcp back 925b28f3b58d mysql:5.7 "docker-entrypoint.s…" About an hour ago Up About an hour 33060/tcp, 0.0.0.0:3308->3306/tcp database ab6efeba59a1 feeder-in_web "docker-entrypoint.s…" About an hour ago Up About an hour 0.0.0.0:8080->3000/tcp web$ docker exec -it 925b28f3b58d mysql -u root -p mysql> show variables like "chara%"; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ 8 rows in set (0.03 sec)
character_set_database | latin1
これを見る限り、MySQLのデフォルトのcharasetになっており、日本語対応になっていない。MySQLデータベースサーバを日本語対応にする
docker-compose.ymlcommand: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci$ docker-compose down $ docker-compose up -d --buildデータベースの再構築
database.ymldefault: &default charset: utf8mb4 #追記 encoding: utf8mb4$ docker-compose exec back sh > rake db:drop > rake db:create > rails db:migrateこれで日本語対応のデータベースになった!
- 投稿日:2020-09-09T19:20:37+09:00
DockerfileにShell関数を書く方法
- 投稿日:2020-09-09T18:38:33+09:00
DockerでRuby on rails6のアプリケーションを環境構築
目標
- ruby on rails6 のアプリケーションをdockerで新規にアプリを立ち上げたい
- DBはMySQLで設定
前提
- Docker on mac
- Rails tutorial完了などruby on rails に関する基礎知識
1.作業ディレクトを作成し、移動する
MacBook-Air ~ % mkdir アプリ名 MacBook-Air ~ % cd アプリ名 MacBook-Air アプリ名 %2.Dockerfileを定義する
FROM ruby:2.6.3 RUN apt-get update -qq && apt-get install -y nodejs # yarnパッケージ管理ツールをインストール # https://classic.yarnpkg.com/en/docs/install/#debian-stable RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list RUN apt-get update && apt-get install yarn WORKDIR /アプリ名 COPY Gemfile /アプリ名/Gemfile COPY Gemfile.lock /アプリ名/Gemfile.lock RUN bundle install COPY . /アプリ名 # Add a script to be executed every time the container starts COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 # Start the main process. CMD ["rails", "server", "-b", "0.0.0.0"]3.Gemfileを作成する
source 'https://rubygems.org' gem 'rails', '~>6'4.空のGemfile.lockを生成する
MacBook-Air アプリ名 % touch Gemfile.lock5.entrypoint.shを作成する
2つ目のところ、自身のアプリ名を入れることに気をつける
#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /アプリ名/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"6.docker-compose.ymlを作成する
webのvolumesのところを自分のアプリ名を入れる
docker-compose.ymlversion: "3" services: db: image: mysql:8.0 command: mysqld --default-authentication-plugin=mysql_native_password environment: MYSQL_ROOT_PASSWORD: root volumes: - ./tmp/db:/var/lib/mysql web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" environment: MYSQL_HOST: db volumes: - .:/アプリ名 ports: - "3000:3000" depends_on: - db7.Rails newをする
ここではオプションとして、オプションでリンクしたサービスを起動しない設定、DBをmysqlにする設定を追加
MacBook-Air アプリ名 % docker-compose run web rails new . --force --no-deps --database=mysql ~ Starting アプリ名_db_1 ... done Building web ~ Successfully built 36d2fef9a8a6 Successfully tagged アプリ名_web:latest8. DBと接続する
passwordとhostに環境変数を設定する
database.yml~ default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: <%= ENV.fetch("MYSQL_ROOT_PASSWORD", "root") %> host: <%= ENV.fetch("MYSQL_HOST", "db") %> ~9.コンテナを起動する
MacBook-Air アプリ名 % docker-compose up ~ web_1 | => Booting Puma web_1 | => Rails 6.0.3.2 application starting in development web_1 | => Run `rails server --help` for more startup options web_1 | Puma starting in single mode... web_1 | * Version 3.12.6 (ruby 2.6.3-p62), codename: Llamas in Pajamas web_1 | * Min threads: 5, max threads: 5 web_1 | * Environment: development web_1 | * Listening on tcp://0.0.0.0:3000 web_1 | Use Ctrl-C to stopこの表示がでたらブラウザで http://localhost:3000/ にアクセスする
Yay! You’re on Rails! と表示がでたらコンテナ起動成功エラー: No such file or directory @ rb_sysopen - /アプリ名/config/webpacker.yml Errno::ENOENT)発生時
MacBook-Air アプリ名 % docker-compose run web rails webpacker:install ~ Webpacker successfully installed ? ?参考文献
https://docs.docker.com/compose/rails/
https://railsdoc.com/rails
- 投稿日:2020-09-09T18:38:33+09:00
DockerでRuby on rails6のアプリケーションを環境構築したメモ
目標
- Ruby on Rails6 のアプリケーションをDockerで新規にアプリを立ち上げたい
- DBはMySQL
前提知識
- Docker on mac
- Rails tutorial完了などRuby on rails に関する基礎知識
1.作業ディレクトを作成し、移動する
MacBook-Air ~ % mkdir アプリ名 MacBook-Air ~ % cd アプリ名 MacBook-Air アプリ名 %2.Dockerfileを定義する
DockerfileFROM ruby:2.6.3 RUN apt-get update -qq && apt-get install -y nodejs # yarnパッケージ管理ツールをインストール # https://classic.yarnpkg.com/en/docs/install/#debian-stable RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list RUN apt-get update && apt-get install yarn WORKDIR /アプリ名 COPY Gemfile /アプリ名/Gemfile COPY Gemfile.lock /アプリ名/Gemfile.lock RUN bundle install COPY . /アプリ名 # Add a script to be executed every time the container starts COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 # Start the main process. CMD ["rails", "server", "-b", "0.0.0.0"]3.Gemfileを作成する
Gemfilesource 'https://rubygems.org' gem 'rails', '~>6'4.空のGemfile.lockを生成する
MacBook-Air アプリ名 % touch Gemfile.lock5.entrypoint.shを作成する
2つ目のところ、自身のアプリ名を入れることに気をつける
entrypoint.sh#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /アプリ名/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"6.docker-compose.ymlを作成する
webのvolumesのところを自分のアプリ名を入れる
docker-compose.ymlversion: "3" services: db: image: mysql:8.0 command: mysqld --default-authentication-plugin=mysql_native_password environment: MYSQL_ROOT_PASSWORD: root volumes: - ./tmp/db:/var/lib/mysql web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" environment: MYSQL_HOST: db volumes: - .:/アプリ名 ports: - "3000:3000" depends_on: - db7.Rails newをする
ここではオプションとして、オプションでリンクしたサービスを起動しない設定、DBをmysqlにする設定を追加
MacBook-Air アプリ名 % docker-compose run web rails new . --force --no-deps --database=mysql ~ Starting アプリ名_db_1 ... done Building web ~ Successfully built 36d2fef9a8a6 Successfully tagged アプリ名_web:latest8. DBと接続する
passwordとhostに環境変数を設定する
database.yml~ default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: <%= ENV.fetch("MYSQL_ROOT_PASSWORD", "root") %> host: <%= ENV.fetch("MYSQL_HOST", "db") %> ~9.コンテナを起動する
MacBook-Air アプリ名 % docker-compose up ~ web_1 | => Booting Puma web_1 | => Rails 6.0.3.2 application starting in development web_1 | => Run `rails server --help` for more startup options web_1 | Puma starting in single mode... web_1 | * Version 3.12.6 (ruby 2.6.3-p62), codename: Llamas in Pajamas web_1 | * Min threads: 5, max threads: 5 web_1 | * Environment: development web_1 | * Listening on tcp://0.0.0.0:3000 web_1 | Use Ctrl-C to stopこの表示がでたらブラウザで http://localhost:3000/ にアクセスする
Yay! You’re on Rails! と表示がでたらコンテナ起動成功エラー: No such file or directory @ rb_sysopen - /アプリ名/config/webpacker.yml Errno::ENOENT)発生時
MacBook-Air アプリ名 % docker-compose run web rails webpacker:install ~ Webpacker successfully installed ? ?参考文献
https://docs.docker.com/compose/rails/
https://railsdoc.com/rails
- 投稿日:2020-09-09T18:38:33+09:00
DockerでRuby on rails6 × MySQLのアプリケーションを環境構築したメモ
目標
- Ruby on Rails6 のアプリケーションをDockerで新規にアプリを立ち上げたい
- DBはMySQL
前提知識
- Docker on mac
- Rails tutorial完了などRuby on rails に関する基礎知識
1.作業ディレクトを作成し、移動する
MacBook-Air ~ % mkdir アプリ名 MacBook-Air ~ % cd アプリ名 MacBook-Air アプリ名 %2.Dockerfileを定義する
DockerfileFROM ruby:2.6.3 RUN apt-get update -qq && apt-get install -y nodejs # yarnパッケージ管理ツールをインストール # https://classic.yarnpkg.com/en/docs/install/#debian-stable RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list RUN apt-get update && apt-get install yarn WORKDIR /アプリ名 COPY Gemfile /アプリ名/Gemfile COPY Gemfile.lock /アプリ名/Gemfile.lock RUN bundle install COPY . /アプリ名 # Add a script to be executed every time the container starts COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 # Start the main process. CMD ["rails", "server", "-b", "0.0.0.0"]3.Gemfileを作成する
Gemfilesource 'https://rubygems.org' gem 'rails', '~>6'4.空のGemfile.lockを生成する
MacBook-Air アプリ名 % touch Gemfile.lock5.entrypoint.shを作成する
2つ目のところ、自身のアプリ名を入れることに気をつける
entrypoint.sh#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /アプリ名/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"6.docker-compose.ymlを作成する
webのvolumesのところを自分のアプリ名を入れる
docker-compose.ymlversion: "3" services: db: image: mysql:8.0 command: mysqld --default-authentication-plugin=mysql_native_password environment: MYSQL_ROOT_PASSWORD: root volumes: - ./tmp/db:/var/lib/mysql web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" environment: MYSQL_HOST: db volumes: - .:/アプリ名 ports: - "3000:3000" depends_on: - db7.Rails newをする
ここではオプションとして、オプションでリンクしたサービスを起動しない設定、DBをmysqlにする設定を追加
MacBook-Air アプリ名 % docker-compose run web rails new . --force --no-deps --database=mysql ~ Starting アプリ名_db_1 ... done Building web ~ Successfully built 36d2fef9a8a6 Successfully tagged アプリ名_web:latest8. DBと接続する
passwordとhostに環境変数を設定する
database.yml~ default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: <%= ENV.fetch("MYSQL_ROOT_PASSWORD", "root") %> host: <%= ENV.fetch("MYSQL_HOST", "db") %> ~9.コンテナを起動する
MacBook-Air アプリ名 % docker-compose up ~ web_1 | => Booting Puma web_1 | => Rails 6.0.3.2 application starting in development web_1 | => Run `rails server --help` for more startup options web_1 | Puma starting in single mode... web_1 | * Version 3.12.6 (ruby 2.6.3-p62), codename: Llamas in Pajamas web_1 | * Min threads: 5, max threads: 5 web_1 | * Environment: development web_1 | * Listening on tcp://0.0.0.0:3000 web_1 | Use Ctrl-C to stopこの表示がでたらブラウザで http://localhost:3000/ にアクセスする
Yay! You’re on Rails! と表示がでたらコンテナ起動成功エラー: No such file or directory @ rb_sysopen - /アプリ名/config/webpacker.yml Errno::ENOENT)発生時
MacBook-Air アプリ名 % docker-compose run web rails webpacker:install ~ Webpacker successfully installed ? ?参考文献
https://docs.docker.com/compose/rails/
https://railsdoc.com/rails
- 投稿日:2020-09-09T18:30:02+09:00
dockerでWebアプリ構築した(1)
自分はdockerを基盤にWebアプリの開発を行っています。
その開発基盤の構築をちょろっとやったので記事に纏めました。
初歩的なものですが、自分の備忘録?的な感じとして記事を書いていきます。Docker images nginx
まず、nginxのdocker imagesを取ってくる。
$ docker pull docker.io/nginx Using default tag: latest latest: Pulling from library/nginx bf5952930446: Already exists cb9a6de05e5a: Pull complete 9513ea0afb93: Pull complete b49ea07d2e93: Pull complete a5e4a503d449: Pull complete Digest: sha256:b0ad43f7ee5edbc0effbc14645ae7055e21bc1973aee5150745632a24a752661 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latestで取得!
docker imagesで確認します。$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx alpine ecd67fe340f9 2 months ago 21.6MBdocker runしていくぜ!
注意: 以下の操作で一部間違ってやっているものがあります。(docker runしているコマンドにミスがあります。)
images⇨container
をしていきます。container作成には、docker runが必須です。
では、行っていきます。$ docker run -d -p 8000:80 --name cesium_nginx -v /マウントするフォルダ:/home ecd67fe340f9 a115c1e7a815a4856b2b51755e217f2cc1aa856c81489d9ae3020f4fefd0883f今回は、ポートを立てるだけでなくマウントもしていきます。
使用オプション
-p
外部からアクセスされるポート番号:コンテナ側のポート番号を指定。
-d
バックグラウンドで実行。
-v マウントするフォルダ:マウント先
フォルダのマウントを実行。-v local:cotainer
--name
コンテナ名を決める。$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a115c1e7a815 ecd67fe340f9 "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:8000->80/tcp cesium_nginxlocalhost:8000をみにいく
http://localhost:8000/
を開くと...こんなものが...なんだこれ...
これは、nginxが正常に動いた証!!!
つまり、成功?
かと、思ったが、、自分のマウントしたフォルダには既にhtmlファイルがあります。
だから、それが表示されないと成功ではない。修正
何が間違っていたか...端的に言えば、マウント先が間違っている。
自分は/home
にマウントしました。
理由は、適当...どこでも良いやって思ってました。そんなあまくなかった...
docker rm や docker stopしました。(そこらへんの処理は省きます)
$ docker run --name cesium_nginx -v /マウントするフォルダ:/usr/share/nginx/html:ro -d -p 8081:80 ecd67fe340f9 f85c35793c4bb7368af7798db788f707bcbd4278bbcfdf87a360f727e6433c00
/usr/share/nginx/html:ro
これが必要でした。さて、これでlocalhost:8081を開きましょう!
きたーーーー
やっと目的の画面が...(この画面はCesium.jsというWebアプリケーションの画面です。ちょっとアレンジ加えていますが...)
まとめ
しっかり仕様書?やしっかり調べてからやっていこう
こっからスタートや!色々いじっていきます。楽しい楽しい開発の始まり~(見ての通り既に開発していましたが...)
- 投稿日:2020-09-09T16:53:37+09:00
Dockerコマンド備忘録
現在立ち上がっているdockerをまとめて落とす
docker ps -a | awk -F ' +' 'NR > 1 {print $7}' | xargs _docker_ rm -fdockerコンテナ内からmacのlocalhostにアクセスしたいとき
host.docker.interna特定のメソッドのみテスト
gradle test --tests "*HogeTest.testNewInstance" -i特定のクラスのみテスト
gradle test --tests "*HogeTest" -iコンテナを一括で消す
docker container list -qf name=zubatoku.*_<name> | xargs docker container rm -f現在起動中のコンテナに関わるものはそのまま残したい場合
docker system prune -af --volumesコンテナを全て消す
docker rm -f $(docker ps -aq)コンテナイメージを全て消す
docker rmi -f $(docker images -q)docker volumeを全て消す
docker volume rm -f $(docker volume ls -q)
- 投稿日:2020-09-09T16:31:48+09:00
EC2にdockerコンテナを立ち上げる(個人的備忘録)
EC2にubuntuのインスタンスを作成し、キーペアを作る
インスタンス作成は割愛
-# キーペアの権限を変える % chmod 400 キーペア.pem -# ubuntuのインスタンスにssh接続する % ssh -i キーペア.pem ubuntu@EC2のパブリックDNS yesキーペアの権限を変える目的は、間違って書き換えた場合、ssh接続できないので「400」と読み取り専用のキーペアとする。EC2のパブリックDNSはインスタンスを停止、起動で変わるので注意!
EC2にdockerをインストール
-# アクセス権限がないので、sudoを使いupdateする。 $ sudo apt-get update -# dockerのインストール $ sudo apt-get install docker.io -# Yを押す -# dockerのバージョンの確認 $ docker -—versionこのままだとubuntuはdockerに権限がないため、コマンドの頭に「sudo」を毎回つけなければならない。なので「docker」というグループを作り、「ubuntu」を入れる。すると「docker」グループに「ubuntu」は属しているため、dockerが使えるようになり、「sudo」なしにコマンドが使えるようになる。
-# 「docker」というグループに「ubuntu」をいれる $ sudo glassed -a ubuntu docker Adding user ubuntu to group docker -# 一度抜けないと反映されない $ exit -# ssh接続する % ssh -i キーペア.pem ubuntu@EC2のパブリックDNS -# dockerコマンドの確認 $ docker imagesdockerコマンドが使えることが確認できる。
Docker imageをtarに圧縮してEC2に送る
-# EC2に送るDocker imageの作成 % mkdir temp_folder % cd temp_folder % vim Dockerfile
DockerfileFROM alpine RUN touch test% docker build .軽量のalpineを作成し、そこに「test」というファイルを作成する。
tarファイルに変換
-# docker save イメージ名 > 新しい名前.tar % docker save b3fc1a6f13e6 > myimage.tar -# tarファイルの確認 % lsSFTPを使ってEC2にアクセスする。
ファイルを転送する時に使うコマンド。
-# sftpに入る(ホストとインスタンスが接続している状態) % sftp -I キーペア.pem ubuntu@EC2のパブリックDNS -# put 送るファイルのパス 送り先のファイルパス sftp> put temp_folder /home/ubuntu -# 別のターミナルを開き、キーペアがあるディレクトリに移動し、ssh接続する。 % ssh -i mydocker.pem ubuntu@ec2-18-183-94-137.ap-northeast-1.compute.amazonaws.com -# ファイルがあるか確認 $ lsファイルがホストからEC2に転送されていることが確認できる。
EC2からホストへファイルを転送する
-# EC2にファイルの作成 $ touch test -# 別のターミナルを開き、ホスト側へ移動、sftpに入る % sftp -I キーペア.pem ubuntu@EC2のパブリックDNS -# testファイルがあることを確認する sftp> ls -# testファイルを取得する sftp> get test -# sftpを抜ける sftp> exitデスクトップに「test」ファイルがあることを確認する
tatファイルをdockerimageに戻す
# ssh接続する % ssh -i キーペア.pem ubuntu@EC2のパブリックDNS # docker load < tarファリルでimageに戻す $ docker load < my image.tar # imageの確認 $ docker images # docker run(alpineはbashがないのでsh) $ docker run -it イメージID sh # lsコマンドでtestファイルがあることを確認 lsDockerfileをEC2に直接送り立ち上げる。
-# sftpに入る % sftp -I キーペア.pem ubuntu@EC2のパブリックDNS -# putでDockerfileを送る、送り先を指定しない場合はubuntuのホームディレクトリにputされる % put Dockerfileの絶対パス -# ssh接続する % ssh -i mydocker.pem ubuntu@ec2-18-183-94-137.ap-northeast-1.compute.amazonaws.com -# Dockerfileの確認 $ ls -# ビルドコンテキストの作成 $ mkdir dsenv_build -# Dockerfileの移動 $ mv Dockerfile dsenv_build/ $ cd dsenv_build -# コンテナを立ち上げる $ docker build .しかし、ストレージ(8GB)が足りずビルドすることができない。
コンピュータのディスク要領の確認
# -hでM,Gバイト表示になる $ df -h Filesystem Size Used Avail Use% Mounted on udev 476M 0 476M 0% /dev tmpfs 98M 768K 98M 1% /run /dev/xvda1 7.7G 5.1G 2.7G 66% / tmpfs 490M 0 490M 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 490M 0 490M 0% /sys/fs/cgroup /dev/loop0 97M 97M 0 100% /snap/core/9804 /dev/loop1 29M 29M 0 100% /snap/amazon-ssm-agent/2012 tmpfs 98M 0 98M 0% /run/user/1000
8GBで「/」はすでに5.1G使っており、残りは2.7GBしかなくbuildする際に、ストレージが足りずにBuildできない。ちなみにLinuxの場合、Dockerオブジェクトの保存場所は「/var/lib/docker/」にある。
EC2のストレージを変更する。
1.EC2のインスタンスのページで「Elastic Block Store」のボリュームをクリックする。
2.任意のインスタンスにチェックし、「アクション」でボリュームの変更を行う。
3.サイズで20GBと設定する。
4.画面を更新し、サイズが20GBになっていることを確認する。
5.インスタンスに反映されていない可能性があるので、インスタンスを再起動しておく。再度buildする。
-# ssh接続 % ssh -i mydocker.pem ubuntu@ec2-18-183-94-137.ap-northeast-1.compute.amazonaws.com -# Dockerfileの場所まで移動する $ cd dsenv_build -# 再度build $ docker build . -# ストレージが20GBになったので、異常なくbuildできる。 $ docker run -v~:/work -p 8888:8888 イメージIDEC2のパブリックDNS:8888で接続できることが確認できる。
コンテナのアクセス権限
-# $ sudo adduser —uid 任意のID ユーザー名(ユーザーはsudo権限がないと作成できないので注意) -# いろいろ聞かれるが今回は全てエンターで省略 $ sudo adduser --uid 1111 aaa -# /home/aaaというディレクトリが作成されているので移動 $ cd /home/aaa -# もう1人のユーザー作成 $ sudo adduser --uid 2222 bbb -# ホームディレクトリに戻る $ cd /home -# ファイルの権限を確認する。 $ ls -la -# aaaとbbbのファイルの権限が確認でき、aaaはbbbのディレクトリに書き込みができないことが確認できる。 -# aaaのユーザーで入る docker run -u 1111 -v /home/aaa:/home/aaa -v /home/bbb:/home/bbb -it ubuntu bash -# idの確認 1111 aaaのユーザーで入っていることが確認できる。 -# bbbディレクトリに移動 $ cd /home/bbb -# ファイルを作成 $ touch testしかし書き込み権限がないため、作成できないことが確認できる。
- 投稿日:2020-09-09T15:23:43+09:00
Docker上のRailsをherokuへデプロイする
herokuへデプロイする練習
Dcokerコンテナ上に、Railsアプリを組んでCircleciを使って自動デプロイまでを一気にやろうとしたら
迷宮入りしたので、原点回帰しようと思います。(第2段)自分の環境
Ruby : 2.6.6
rails : 6.0.3.2
git : 2.23.0
heroku-cli : 7.42.13 darwin-x64 node-v12.16.2
Docker : 19.03.12開発環境は、MySQLで
本番環境は、PostgreSQLというパターンで組んでみようと思います。手元のDocker上にRailsアプリを用意する
まずは、アプリを作るディレクトリを作成し、そこにtouchコマンドで必要な諸々を用意します。
terminal$ touch {Dockerfile,docker-compose.yml,Gemfile,Gemfile.lock,entrypoint.sh}DockerfileFROM ruby:2.6 RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update -qq \ && apt-get install -y nodejs yarn \ && mkdir /heroku_app WORKDIR /heroku_app COPY Gemfile //Gemfile COPY Gemfile.lock /heroku_app/Gemfile.lock RUN bundle install COPY . /heroku_app COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3006 CMD ["rails", "server", "-b", "0.0.0.0"]docker-compose.ymlversion: '3' services: db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: password ports: - '3306:3306' command: --default-authentication-plugin=mysql_native_password volumes: - mysql-data:/var/lib/mysql:cached web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3006 -b '0.0.0.0'" volumes: - .:/heroku_app ports: - "3006:3000" depends_on: - db stdin_open: true tty: true command: bundle exec rails server -b 0.0.0.0 volumes: mysql-data: driver: localGemfilesource 'https://rubygems.org' rails ‘6.0.3’entrypoint.sh#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /heroku_app/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"上記5点を用意できれば、下記コマンドを実行しRailsアプリを作成します。
terminal$docker-compose run web rails new . --force --no-deps --database=mysql併せて、テキトーな中身を作っておきます。
$ docker-compose run web rails g scaffold blog title:string body:text $ docker-compose run web rails db:migrate $ docker-compose up -dherokuへデプロイする準備
続いて、Railsアプリをherokuにデプロイする前に、本番環境用にpostgreSQLを用意します。
- config/database.ymlの設定
- Gemfile にpgを追加
- config/enviroments/deviropment.rbの設定config/database.ymlの設定
config/database.ymlproduction: <<: *default adapter: postgresql encoding: unicode pool: 5Gemfileの設定
本番環境用にgemファイルを用意します。
productionのグループにpgを追加します。
また、MySQLは開発環境用として扱う様にするために、group :development, :test do
の中へ移動させます。Gemfilegroup :production do gem 'pg', '~> 0.19.0' endconfig/enviroments/deviropment.rbの設定
Rails6特有ですが、DNS離バインディング攻撃からの保護が入っているらしく、
hostを入れてあげる必要があります。config/enviroments/deviropment.rbconfig.hosts << "radiant-springs-45017.herokuapp.com"下記記事を参考にさせていただきました。
https://qiita.com/kodai_0122/items/67c6d390f18698950440編集を終えたら、ビルドします。
terminaldocker-compose build $docker-compose run web rails db:create $docker-compose up -dあとは、コマンド打って、ルンルンとherokuへデプロイします。
$ docker-compose down #一度落としておかないとエラーになる可能性があるとのこと $ heroku login $ heroku create アプリ名もしくは空欄 $ heroku container:login $ heroku container:push web $ heroku adding:create heroku-postgresql:hobby-dev $ heroku container:release web $ heroku open終わり!
割愛しましたが、herokuへデプロイした際にエラーが発生しました。
その際は、ターミナル上で$ heroku logs --tail
等を打ち、エラーを調べて解決させました。
成功された記事を参考した場合でも、環境の違い等でエラーが発生しうるので、理解のために都度調べる癖をつけるのは大事だと思った次第です。
- 投稿日:2020-09-09T08:07:19+09:00
初心者がdocker for macをインストールして起動してみる
インストールまで
対象者
dockerって何?
動機
php5.Xを使う機会がありました。
php5.xはサポート期間が終了しています。
dockerを使うのが分かりやすかったです。参考記事
DockerをMacにインストールする(更新: 2019/7/13)
アカウント登録
dockerバージョン確認
docker versionDouble-click Docker.dmg to start the install process.
When the installation completes and Docker starts, the whale in the top status bar shows that Docker is running, and accessible from a terminal.gitバージョン確認
git versiondockerとは?
dockerはコンテナ管理ソフトウェア。
installをしたので使ってみましょう。dockerのコマンドを使ってみる
nginxをpullする
cmddocker run -d -p 80:80 --name {コンテナ名} nginx起動しているnginxを止める
cmddocker container stop {コンテナ名}起動しているnginxを起動
cmddocker container start {コンテナ名}起動しているコンテナのリストを表示
cmddocker container lscmddocker container ls -aコンテナの削除
cmddocker container rm {コンテナ名}イメージの削除
cmddocker image rm {ID}所要時間
30分ぐらいでできると思います。
ここまでの疑問
- nginxって何?
- imagetって何?