- 投稿日:2019-08-19T23:57:09+09:00
AzureAppServiceでDockerを使ってWebアプリを公開する
概要
試しに利用してみたら便利だったので、記録として残します。
ただ、個人的にはVPC内に置く機能がβ版だったり、Webアプリとしてしか公開ができなかったり、
本番運用としてはログ周りの機能が弱いとも感じるので趣味サイトとして利用することを前提とした方がいいと思います。仕様等
AzureAppServiceを利用するにはAppServicePlanとAppServiceを作成する必要があります。
例えるとAppServicePlanがサーバであり、AppService自体はアプリケーションを管理する物という感じ。Azure CLIのインストール
$ brew install azure-cliazコマンドのリファレンス
- コマンドのリファレンスはこちら
- az xxx --helpからも確認できます
構築手順
RailsのWelcome画面を出すまでところまでとします。
- Azure環境にログイン
- ResourceGroupの作成
- AzureContainerRegistry(以下ACR)の作成
- RailsのDockerImageの準備
- ACRにDockerImageのPush
- AppServicePlanの作成
- AppServiceの作成
- CDの設定
- 環境変数の設定
- 確認
1. Azure環境にログイン
ブラウザでログイン画面が表示されるのでログインする
$ az login2. ResourceGroupの作成
これに各種リソースを登録していきます
$ az group create --name nagi125-dev --location japaneast3. AzureContainerRegistryの作成
これにDockerImageを登録していきます
$ az acr create --resource-group nagi125-dev --name nagi125acr --sku Basic --admin-enabled true --location japaneast4. RailsのDockerImageの準備
Railsアプリケーションの作成
$ rails new rails-sample-app $ cd ./rails-sample-app $ touch Dockerfile $ vim DockerfileDockerfileの準備
FROM ruby:2.6.3 ENV TZ Asia/Tokyo ENV RAILS_ENV development RUN apt-get update -qq && \ apt-get install --no-install-recommends -y netcat build-essential libpq-dev nodejs && \ apt-get clean && \ rm -rf /var/cache/apt RUN gem install bundler COPY Gemfile Gemfile.lock /app/ WORKDIR /app RUN bundle install COPY . /app ENTRYPOINT ["rails", "server", "-b", "0.0.0.0"]Imageの作成とACR用のタグをつける
$ docker build -t nagi125/rails-sample-app . $ docker tag nagi125/rails-sample-app:latest nagi125acr.azurecr.io/nagi125/rails-sample-app:latest5. ACRにDockerImageのPush
$ az acr login --name nagi125acr $ docker push nagi125acr.azurecr.io/nagi125/rails-sample-app:latest6. AppServicePlanの作成
$ az appservice plan create --resource-group nagi125-dev --name rails-sample-app-plan --sku B1 --location japaneast --is-linux7. AppServiceの作成
AppServicePlanとACRのImageを指定して作成する
$ az webapp create --resource-group nagi125-dev --plan rails-sample-app-plan --name rails-sample-app --deployment-container-image-name nagi125acr.azurecr.io/nagi125/rails-sample-app:latest8. CD設定
これを設定する事でImageをPushしてしばらくするとAppServiceに反映されるようになります。
※ 2-3分経っても反映されない場合AppServiceの再起動をしてみるとよいかも。AppServiceとACRの紐付け
$ az webapp config container set --name rails-sample-app --resource-group nagi125-dev --docker-custom-image-name nagi125acr.azurecr.io/nagi125/rails-sample-app:latest --docker-registry-server-url http://nagi125acr.azurecr.io --docker-registry-server-user nagi125acr --docker-registry-server-password xxxxx※ passwordはコマンドから確認できないため下記手順で確認する
CD設定
webhookのuriは返ってきた値を利用する
※ zsh等を利用している人は$のエスケープを忘れないようにしてください$ az webapp deployment container config -g nagi125-dev -n rails-sample-app --enable-cd true $ az acr webhook create -n railsSampleApp -r nagi125acr --scope nagi125/rails-sample-app:latest --location japaneast --uri xxxxx --actions push delete9. 環境変数の設定
$ az webapp config appsettings set --settings RAILS_ENV=development -g nagi125-dev -n rails-sample-app10. 確認
$ az webapp browse --resource-group nagi125-dev --name rails-sample-app
- 投稿日:2019-08-19T23:57:09+09:00
AzureAppServiceでContainerを使ってWebアプリを公開する
概要
試しに利用してみたら便利だったので、記録として残します。
ただ、個人的にはVPC内に置く機能がβ版だったり、Webアプリとしてしか公開ができなかったり、
本番運用としてはログ周りの機能が弱いとも感じるので趣味サイトとして利用することを前提とした方がいいと思います。仕様等
AzureAppServiceを利用するにはAppServicePlanとAppServiceを作成する必要があります。
例えるとAppServicePlanがサーバであり、AppService自体はアプリケーションを管理する物という感じ。Azure CLIのインストール
$ brew install azure-cliazコマンドのリファレンス
- コマンドのリファレンスはこちら
- az xxx --helpからも確認できます
構築手順
RailsのWelcome画面を出すまでところまでとします。
- Azure環境にログイン
- ResourceGroupの作成
- AzureContainerRegistry(以下ACR)の作成
- RailsのDockerImageの準備
- ACRにDockerImageのPush
- AppServicePlanの作成
- AppServiceの作成
- CDの設定
- 環境変数の設定
- 確認
1. Azure環境にログイン
ブラウザでログイン画面が表示されるのでログインする
$ az login2. ResourceGroupの作成
これに各種リソースを登録していきます
$ az group create --name nagi125-dev --location japaneast3. AzureContainerRegistryの作成
これにDockerImageを登録していきます
$ az acr create --resource-group nagi125-dev --name nagi125acr --sku Basic --admin-enabled true --location japaneast4. RailsのDockerImageの準備
Railsアプリケーションの作成
$ rails new rails-sample-app $ cd ./rails-sample-app $ touch Dockerfile $ vim DockerfileDockerfileの準備
FROM ruby:2.6.3 ENV TZ Asia/Tokyo ENV RAILS_ENV development RUN apt-get update -qq && \ apt-get install --no-install-recommends -y netcat build-essential libpq-dev nodejs && \ apt-get clean && \ rm -rf /var/cache/apt RUN gem install bundler COPY Gemfile Gemfile.lock /app/ WORKDIR /app RUN bundle install COPY . /app ENTRYPOINT ["rails", "server", "-b", "0.0.0.0"]Imageの作成とACR用のタグをつける
$ docker build -t nagi125/rails-sample-app . $ docker tag nagi125/rails-sample-app:latest nagi125acr.azurecr.io/nagi125/rails-sample-app:latest5. ACRにDockerImageのPush
$ az acr login --name nagi125acr $ docker push nagi125acr.azurecr.io/nagi125/rails-sample-app:latest6. AppServicePlanの作成
$ az appservice plan create --resource-group nagi125-dev --name rails-sample-app-plan --sku B1 --location japaneast --is-linux7. AppServiceの作成
AppServicePlanとACRのImageを指定して作成する
$ az webapp create --resource-group nagi125-dev --plan rails-sample-app-plan --name rails-sample-app --deployment-container-image-name nagi125acr.azurecr.io/nagi125/rails-sample-app:latest8. CD設定
これを設定する事でImageをPushしてしばらくするとAppServiceに反映されるようになります。
※ 2-3分経っても反映されない場合AppServiceの再起動をしてみるとよいかも。AppServiceとACRの紐付け
$ az webapp config container set --name rails-sample-app --resource-group nagi125-dev --docker-custom-image-name nagi125acr.azurecr.io/nagi125/rails-sample-app:latest --docker-registry-server-url http://nagi125acr.azurecr.io --docker-registry-server-user nagi125acr --docker-registry-server-password xxxxx※ passwordはコマンドから確認できないため下記手順で確認する
CD設定
webhookのuriは返ってきた値を利用する
※ zsh等を利用している人は$のエスケープを忘れないようにしてください$ az webapp deployment container config -g nagi125-dev -n rails-sample-app --enable-cd true $ az acr webhook create -n railsSampleApp -r nagi125acr --scope nagi125/rails-sample-app:latest --location japaneast --uri xxxxx --actions push delete9. 環境変数の設定
$ az webapp config appsettings set --settings RAILS_ENV=development -g nagi125-dev -n rails-sample-app10. 確認
$ az webapp browse --resource-group nagi125-dev --name rails-sample-app
- 投稿日:2019-08-19T20:47:14+09:00
DockerでFlask開発環境構築
使うもの
- macOS High Sierra
- Docker
- VSCode
- brew
VSCodeの設定
まずはVSCodeにPythonの拡張機能をインストールします。
macに入っているデフォルトのPython2は推奨されないみたいなので、python3をインストールします。
brew install python3
「Select Python Interpreter」を押してPython3を設定。
あとは以下の警告も消すために「install」を押してpipもインストールしておきます。
pip3 --version
でバージョン情報が出てばインストール完了。VSCodeの設定はここで完了。
Dockerの設定
ディレクトリ構成はこんな感じ
root ├── Dockerfile ├── docker-compose.yml └── main.pyそれぞれのファイルは以下の通り
DockerfileFROM python:3.7 WORKDIR /app RUN pip install flask RUN pip install xmltodict CMD [ "python", "main.py" ]docker-compose.ymlversion: '3' services: api: build: . ports: - 80:8080 volumes: - ./main.py:/app/main.py tty: truemain.pyfrom flask import Flask, jsonify, request import json import urllib.request import xmltodict app = Flask(__name__) app.config['JSON_AS_ASCII'] = False @app.route("/", methods=['GET']) def index(): # パラメーター取得 keyword = request.args.get('keyword') # API通信 req = "https://news.google.com/rss/search?q=" + urllib.parse.quote_plus(keyword, encoding='utf-8') + "&hl=ja&gl=JP&ceid=JP:ja" # 結果取得 with urllib.request.urlopen(req) as res: body = res.read() # XML → 辞書に変換 dict = xmltodict.parse(body) # 辞書 → JSONに変換 data = json.dumps(dict, indent=4, ensure_ascii=False) # 結果返却 return data if __name__ == "__main__": app.run(host='0.0.0.0', port=8080)keywordパラメータで受け取った文字列でGoogleNewsのRSS取得してJSON形式で返すだけのAPIです。
動作確認
docker-compose up -d
でコンテナ起動あとはこんな感じでAPI叩いて結果返ってくれば終わり
http://localhost?keyword=スマホ以上。サクッとFlask環境構築でした。
- 投稿日:2019-08-19T18:13:54+09:00
docker上のmysqlのデータバックアップ
- 投稿日:2019-08-19T17:02:49+09:00
AWS Batchでのマルチスレッド処理では、コンテナあたりのスレッド数に要注意
AWS Batchでのマルチスレッド処理では、コンテナあたりのスレッド数に要注意
AWS Batchのジョブ設定には、VCPUという項目がある。
設定の名称からすると、コンテナ内から見えるCPU数が変わるのではないか?という期待を持ってしまう。しかし、この設定の実態はただの優先度設定である (docker runの--cpu-sharesオプションにマップされている)。
ここに何を設定したとしても、コンテナ内からは、Dockerホストに実装されているCPUコアが全て見えてしまう。何が問題になるか
ミスの例
OpenMPなどの並列化プラットフォームを利用すると、デフォルトでは、システムに実装されているCPU数分のスレッドが起動する動作になっていることが多い。
そのような動作をするプログラムを動かす際、以下のような(間違った)設定をしたとする。
ジョブ定義:
VCPU=2、メモリ8GiB
※「全スレッド共有で4GiB使用し、さらに1スレッドごとに2GiBのメモリを使用する」という設計のプログラムを動かすものとする。
※2スレッド動作時は、4 + 2 * 2で8GiB必要となる。コンピューティング環境:
m4.16xlarge (32物理コア・ 256 GiBメモリ)
設定時の想定では、16コンテナで32スレッドが起動し、16 * 8 = 128GiBのメモリが消費される。
しかしこの場合、実際には、16コンテナ * 32スレッド(物理コア数分) = 512スレッドが起動する。発生する問題
事故パターン1 OOM
512スレッド * 2GiBだけでも1TiBのメモリが必要になるが、動作しているEC2インスタンスには256GiBしか実装されていない。
そこで、OOM Killerさんが目覚める。_人人人人人人_
> 突然の死 <
 ̄Y^Y^Y^Y^Y^Y^ ̄事故パターン2 性能劣化
スレッドごとに必要なメモリが少なく、OOMが起きなかったとする。
それでも、処理の大半が演算の場合、CPUの奪い合い(コンテキストスイッチ祭り)が発生する。_人人人人人人人_
> 無駄に遅い <
 ̄Y^Y^Y^Y^Y^Y^Y^ ̄ただし、この動作は、インスタンスに対して起動中のコンテナが少ない場合にはメリットとなるので、一長一短。
コンテナがCPU性能を目いっぱい使うので処理がすぐ終わり、ジョブが無くなったインスタンスがスケールインすることでコストが下がる。
大抵の場合はメリットのほうが大きいかも。どうすりゃいいのか
スレッド数に比例して消費メモリが(大きく)増える設計/実装は避ける
上記が無理なら、起動するスレッド数を固定する
ハードコードではなく、環境変数経由で指定できるようにして、ジョブ定義で調整するとベター。
OpenMPならデフォルトでOMP_NUM_THREADS環境変数によるスレッド数指定に対応している。
- 投稿日:2019-08-19T16:34:38+09:00
macOSでDockerコマンドの入力補完を有効化する手順
1.
bash-completion
をインストールするbash$ brew install bash-completion2.
.bashrc
と.bash_profile
に以下の内容を追加する.bashrcif [ -f `brew --prefix`/etc/bash_completion ]; then . `brew --prefix`/etc/bash_completion fi.bash_profileif [ -f ~/.bashrc ]; then . ~/.bashrc fi3. Dockerのシンボリックリンクを追加する
bash$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker.bash-completion /usr/local/etc/bash_completion.d/docker $ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-machine.bash-completion /usr/local/etc/bash_completion.d/docker-machine $ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-compose.bash-completion /usr/local/etc/bash_completion.d/docker-compose参考文献
- 投稿日:2019-08-19T16:34:38+09:00
MacでDockerコマンドの入力補完を有効化する手順
1.
bash-completion
をインストールする.bash$ brew install bash-completion2.
.bashrc
と.bash_profile
に以下の内容を追加する..bashrcif [ -f `brew --prefix`/etc/bash_completion ]; then . `brew --prefix`/etc/bash_completion fi.bash_profileif [ -f ~/.bashrc ]; then . ~/.bashrc fi3. Dockerのシンボリックリンクを追加する.
bash$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker.bash-completion /usr/local/etc/bash_completion.d/docker $ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-machine.bash-completion /usr/local/etc/bash_completion.d/docker-machine $ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-compose.bash-completion /usr/local/etc/bash_completion.d/docker-compose参考文献
- 投稿日:2019-08-19T16:15:13+09:00
[2019-08-19] Ubuntu 18.04+Docker(19.03)+NVIDIA GPU環境セットアップ
やり方がまた変わっていたのでメモしておきます。
$ grep PRETTY_NAME /etc/os-release PRETTY_NAME="Ubuntu 18.04.3 LTS"(標準で入るドライバを無効化する作業がまず必要かもしれない)
Dockerのインストール
https://docs.docker.com/install/linux/docker-ce/ubuntu/
にしたがってやる。$ sudo apt-get update $ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - $ sudo apt-key fingerprint 0EBFCD88 $ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" $ sudo apt-get install docker-ce docker-ce-cli containerd.io $ docker -v Docker version 19.03.1, build 74b1e89https://docs.docker.com/install/linux/linux-postinstall/
にしたがってやる。$ sudo usermod -aG docker $USER (logout -> login) $ docker run hello-world Hello from Docker! ...NVIDIAドライバ
$ lspci | grep NVIDIA 00:09.0 VGA compatible controller: NVIDIA Corporation GP102 [GeForce GTX 1080 Ti] (rev a1) $ sudo apt install nvidia-headless-430 nvidia-utils-430DockerのNVIDIA対応のためのパッケージ
https://github.com/NVIDIA/nvidia-docker
にしたがってやる。$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list $ sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit確認
$ sudo reboot $ nvidia-smi ... | NVIDIA-SMI 430.26 Driver Version: 430.26 CUDA Version: 10.2 | ... $ docker run --gpus all --rm nvidia/cuda nvidia-smi ... | NVIDIA-SMI 430.26 Driver Version: 430.26 CUDA Version: 10.2 | ...
- 投稿日:2019-08-19T15:16:45+09:00
Vagrant+VirtualBoxによるDocker環境構築
はじめに
これまで.NETの開発をメインでやってきて、一昨年からPHPのプロジェクトに参画した。
それまで VM Wareを使っていたとは言え、普段意識しないし、コンテナとかも使ったことが無かったが、
PHPのプロジェクトではVagrantやDockerなど(自分的には)最新技術に触れて衝撃を受けた。今更ながら勉強する為、まずはPythonの開発環境をDockerで用意しようと考えたが、
Winodws 7 な環境しか手元にない。Dockerは、LinuxもしくはWindowsではWindows 10 からしか使えないので、
Vagrant+VirtualBoxで用意した仮想環境(CentOS)へDockerを載せて環境を用意してみます。Vagrant
- 構成情報を記載した設定ファイル(vagrantfile)を元に、仮想環境の構築から設定まで自動でやってくれます。
- https://ja.wikipedia.org/wiki/Vagrant_(ソフトウェア)
VirtualBox
- 現在利用しているOS(Windows7)上で、別のOS(今回はCentOS)を実行できる仮想化ソフトウェア。
- 現在利用しているOS(Windows7)をホストOS、VirtualBox上に構築したOS(CentOS)をゲストOSと呼ぶ。
- ホストOSでは導入できないソフトウェア(今回はdocker)を利用したい場合や、開発チーム全体で開発環境を統一したい場合、もしくは単にホストOSを汚したく無い場合にも利用する。
- https://ja.wikipedia.org/wiki/VirtualBox
今回の構築環境
- Vagrant+VirtualBoxで、CentOSを載せて、そこでDockerを動作させコンテナを起動します。
- イメージは↓こんな感じ。
用語の定義
ホストとかゲストとかが分かりにくいと思うので、この後の文章では以下のように用語を使います。
Windows 7 VirtualBox内のCentOS CentOS内のDockerコンテナ ホスト ゲスト 又は Dockerホスト Dockerコンテナ インストール
全て仮想環境上で環境構築する為、基本的にWindows7環境は汚れませんが、
VagrantとVirtualBoxだけはインストールする必要があります。
VirtualBox
\https://www.virtualbox.org/wiki/Downloads環境構築(仮想環境構築)
コマンドプロンプトを起動し、適当なフォルダへ移動します。
> d: > cd d:\workCentOSのイメージをダウンロードします。(これ、結構かかります)
> vagrant box add centos/7CentOS起動用のVagrantfileの雛形を作成します。
> vagrant init centos/7作成したVagrantfileの雛形をカスタマイズします。
D:\work フォルダに Vagrantfileファイルが出来ているので、テキストエディタで開いて、以下の編集を行います。
以下の行のコメントアウトを解除するだけです。Vagrantfile35| config.vm.network "forwarded_port", guest: 80, host: 8080
- 35行目の編集はホストOSとゲストOS間のポートマッピング設定です。後でホストOSのブラウザからコンテナ上のWebAppへアクセスする為に必要です。
さあ、Vagrantを起動しましょう。
> vagrant upカレントフォルダのvagrantfileを参照して、そこに記載してある仮想環境を構築、起動します。
恐らくこれで、仮想環境(CentOS)が起動しているので、仮想環境にSSHで接続しましょう。
> vagrant ssh環境構築(コンテナ環境構築)
ここからはDockerコンテナを利用する為の準備をしていきます。
Dockerを利用するのに必要なパッケージ(yum-utils, device-mapper-persistent-data, lvm2)をインストールします。
$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2Dockerをダウンロードするリポジトリをyum(パッケージ管理)に追加します。
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repoyumのパッケージインデックスを更新(DockerのINSTALLやUPGRADEの前に一回実行することが推奨されている)
$ sudo yum makecache fast最新版のDockerをインストールします。
$ sudo yum install docker-ceDockerデーモンを起動します。
$ sudo systemctl start dockerDockerコンテナ動作確認
これでDockerの起動まではできました。
(DockerイメージからDockerコンテナを作り出して起動する為のソフトウェアが動きました)
Dockerの動作確認の為、DockerイメージからDockerコンテナを起動して動作確認をしてみます。ここでは、training/webappというWebアプリケーション動作確認用コンテナを持ってきて起動してみます。
(やっぱりブラウザとかで動いているのが見えるのがいいよね)$ sudo docker run -d -p 80:5000 training/webapp python app.py
- -dオプションはバックグランド実行用のオプションです。これが無いと、「training/webapp」が終わるまで他のコマンドが打てません。
- -pオプションはポートマッピングです。vagrantfileでホストOSとゲストOS間で8080→80でマッピングしたポートを、さらに80→5000にマッピングします。
- 「python app.py」は「training/webapp」コンテナ内で実行するコマンドです。(とりあえずおまじないだと思って入力)
「training/webapp」イメージは350MBくらいあるので、少しダウンロードに時間がかかります。
動作確認はホストOS(Windows7)のブラウザで以下のURLを指定してください。http://localhost:8080/以下のように出てくればOKです。
ホストOSとゲストOS間のポートマッピングはvagrantfileで 8080→80 で設定されており、
上記のdocker runコマンドで -p を指定して、ゲストOSとdockerコンテナ間のポートマッピングを 80→5000 で設定しています。その為、ホスト側でのポート指定は8080になります。
コンテナの停止、他
Dockerコンテナを確認します。
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1c763df10ac5 6fae60ef3446 "python app.py" About a minute ago Up About a minute 0.0.0.0:80->5000/tcp frosty_wing起動しているDockerコンテナをコンテナID(ここでは、1c763df10ac5)を指定して、停止します。
$ sudo docker stop 1c763df10ac5停止されたか確認しましょう。(先ほどまで表示されていたコンテナ(1c763df10ac5)が消えています)
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES起動しているコンテナは無くなりましたが、コンテナ自体は残っていて、-aオプションで全てのコンテナが表示できます。
$ sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1c763df10ac5 6fae60ef3446 "python app.py" 8 minutes ago Exited (137) 3 minutes ago frosty_wingこのコンテナも削除してみましょう。
コンテナの削除は docker rm です。$ sudo docker rm 1c763df10ac5 $ sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESこれでコンテナは消えましたが、イメージは残っています。
$ sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE training/webapp latest 6fae60ef3446 4 years ago 349MB折角なので、イメージも削除しましょう。
イメージの削除は docker rmi です。$ sudo docker rmi 6fae60ef3446 Untagged: training/webapp:latest Untagged: training/webapp@sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d Deleted: sha256:6fae60ef344644649a39240b94d73b8ba9c67f898ede85cf8e947a887b3e6557 Deleted: sha256:875bde2b9e2d99e7c1362993645a474fe621475c6fc1b1623c9ed5312b7bdeae Deleted: sha256:bbdb5ee3757ef8f2633694016df5840fc3410422b37c22f98c0300e295ce75cc Deleted: sha256:d718446240e3f48a904ad4bbf2a1f61737c5d70df35b8210d674a9517cdc9803 Deleted: sha256:a890440f4933412f9aafb056eb2f07f2276ed756631a81e960d4a8a6de5857a3 Deleted: sha256:68a74799a9e67953725058ef21a530f100025088943446aa60c73fba7beebd47 Deleted: sha256:b23e4b6b440d0e9ab4ffd7852fbf81edd6d5eb606e24d4950d83502e14af2856 Deleted: sha256:f115b0453c71fb4d21fdb6f579201984bd5033ae28ed5908978576a19282418b Deleted: sha256:b0da82df3229cd06a2992449f2310caaa42f09fdfb088f4a98c5ea587ea85c7e Deleted: sha256:f6f162dad6e64715d3d07e21d4574733860a557f2f89228d07909c1f6f04e882 Deleted: sha256:088f9eb16f16713e449903f7edb4016084de8234d73a45b1882cf29b1f753a5a Deleted: sha256:799115b9fdd1511e8af8a8a3c8b450d81aa842bbf3c9f88e9126d264b232c598 Deleted: sha256:3549adbf614379d5c33ef0c5c6486a0d3f577ba3341f573be91b4ba1d8c60ce4 Deleted: sha256:1154ba695078d29ea6c4e1adb55c463959cd77509adf09710e2315827d66271a $ sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZEバイバイ
コンテナを抜けます。
$ exit仮想マシン(centos)を停止します。
> vagrant halt ==> default: Attempting graceful shutdown of VM...仮想マシンの一覧は以下のコマンドで確認できます。
> vagrant box list centos/7 (virtualbox, 1905.1)おわりに
とりあえず、Vagrant+VirtualBox上のCentOSでDockerコンテナを起動するところまでできました。
当初は仮想環境とDockerイメージとDockerコンテナがゴチャゴチャになっていましたが、
実際に手を動かして環境を作っていくと、理解が深まりました。参考
https://www.tohuandkonsome.site/entry/2018/03/21/193730
https://qiita.com/inakadegaebal/items/be9fecce813cebec5986
- 投稿日:2019-08-19T08:23:41+09:00
Vue.js & Django を Docker と組み合わせてSPA+APIサーバー環境をつくる
はじめに
今回は、Django REST Frameworkを使った、
Vue.jsをSPAとして運用できる環境の作り方をシェアできればと思います。Docker Composeを使うので、本番で使うときはGKEなどの
モダンなコンテナ型オーケストレーションツールを選択可能かつ、開発でも
メンバーの増員などに柔軟に対応できる環境を作れたらと思います。今回は抜粋で書いているので、
不足等ございましたら、ご連絡よろしくお願いいたします。構成
構成は下記のような形にします。
本来だと下記に+DBもあるような構成が基本ですが、
コンテナ上で動かす場合と、クラウドのDBサービスを使用する場合など
多岐の選択があるため、今回はなしとします。サーバー構成
サーバー名 名称 ポート番号 開発サーバー(Vue.js) front 8080 APIサーバー(Django) back 8001 Webサーバー(Nginx) web 8000 Docker Compose ファイルで骨組みを作る
最初にdocker-compose.ymlファイルと各種サーバーのDockerfileを作成して、
骨組みを形作っていきます。1. docker-compose.ymlを作成
注意点としては、バックエンド側のstaticファイルをnginxに置いて
配信可能とする点です。
今回はAPIサーバーとしての使用のため、不要と思われますが、
djangoのデバッグ画面(管理画面など)を表示する際に使用できるので、
volumesにて、同期します。
基本的に起動は、拡張していくことも考えて、
Shellファイルに落とし込んでいきます。
(直で記載でも良いとは思います。)docker-compose.ymlversion: '3' services: web: build: context: ./ dockerfile: ./web/Dockerfile environment: TZ: 'Asia/Tokyo' ports: - 8000:8000 volumes: - ./web/logs/nginx/:/var/log/nginx/ - ./web/uwsgi_params:/etc/nginx/uwsgi_params - ./back/static:/var/www/static/ depends_on: - back back: build: context: ./back dockerfile: Dockerfile command: 'sh /server/start.sh' expose: - "8001" volumes: - ./back:/server/ front: build: context: ./front command: 'sh /app/start.sh' volumes: - ./front:/app/:cached - ./front/node_modules:/app/node_modules ports: - "8080:8080"2. DockerFile フロントエンド側を作成
npmを使用するために、nodeイメージを入れます。
後ほど立ち上げるためにコメントアウトなども挟むので、
一旦スキップしても構いません。Dockerfile(フロントエンド)FROM node:10.7.0 WORKDIR /app RUN npm install -g @vue/cli ADD ./package.json /app/package.json RUN npm install ADD ./start.sh /app/start.sh3. DockerFile バックエンド側を作成
バックエンド側をゴリゴリ書いていきます。
ライブラリのインストールも都度できるように
requirements.txt経由でインストールします。Dockerfile(バックエンド)FROM python:3.7 ENV PYTHONUNBUFFERED 1 WORKDIR /server ADD . /server/ RUN pip install --upgrade pip RUN pip install -r requirements.txt4. DockerFile Webサーバー側を作成
設定ファイル、Vue.jsで作成しビルドしたものを格納します。
バージョンはお好みのものをご使用ください。Dockerfile(Webサーバー)FROM nginx:1.11.7 # 設定ファイル ADD ./web/nginx.conf /etc/nginx/nginx.conf ADD ./web/default.conf /etc/nginx/sites-available/default ADD ./web/default.conf /etc/nginx/sites-enabled/default ADD ./web/uwsgi_params /etc/nginx/uwsgi_params RUN mkdir /var/www RUN mkdir /var/www/front RUN mkdir /var/www/staticここまで作成するとある程度骨組み部分は出来上がった状態になります。
ここから、実際にサーバーとして使用できるように
各サーバー内に手を加えて初期構築をしていきます。フロントエンド側を作成
Vue.jsを使えるようにVue CLIを導入して、
使用できる状態にしていきます。
エラーを防ぐために一旦Dockerfileで書いた下記をコメントアウトしますFROM node:10.7.0 WORKDIR /app RUN npm install -g @vue/cli # ADD ./package.json /app/package.json # RUN npm install # ADD ./start.sh /app/start.shVue CLIを入れることで、Vueの開発環境を簡単に作成することができます。
早速Terminalからプロジェクトを作成し、開発サーバーとして立ち上げてみましょう。
各種設定方法を聞かれますが、enterで進んでいくとデフォルトのものがインストールされます。ターミナル// hoge-projectにはプロジェクト名を入力してください。 $ docker-compose run front vue create hoge-project先ほどDockerfileに入力したコメントアウトを外して、
start.shを軽く記載した後、立ち上げてみましょう。
(プロジェクト先に向き先を当てるため、ファイルの向き先も変更するか、
プロジェクトフォルダを移動して、動くか確認してみてください。)start.shnpm run serveターミナル$ docker-compose build front $ docker-compose up -d frontローカルホストで確認すると無事立ち上がっているかと思います。
バックエンド側を作成
次にDjango側を作成していきます。
ターミナルからDjangoアプリの初期作成コマンドを打ちます。ターミナル$ docker-compose exec back django-admin startproject mysite次にアプリケーションを作成します。
最後の確認の際に使います。ターミナル$ docker-compose exec back python mysite/manage.py startapp testapi起動用のシェルも書いておきます。
start.sh#!/bin/bash sleep 5 python manage.py makemigrations python manage.py migrate python manage.py collectstatic --noinput uwsgi --socket :8001 --module mysite.wsgiDjango REST Frameworkを使用するので
インストールする設定ファイルに記載します。requirements.txtdjango>=2.1.10 uwsgi==2.0.17.1 djangorestframework==3.8.2一旦ここまでで、最後に疎通確認するので、
次に進みます。Webサーバーを立てる
nginx.conf, default.conf, uwsgi_paramsなどの
設定ファイルを作成していきます。1. nginx.conf
nginx.confuser www-data; worker_processes auto; pid /run/nginx.pid; daemon off; events { worker_connections 65535; multi_accept on; use epoll; } http { sendfile on; tcp_nopush on; tcp_nodelay on; types_hash_max_size 2048; client_max_body_size 20M; keepalive_timeout 3600; proxy_connect_timeout 3600; proxy_send_timeout 3600; proxy_read_timeout 3600; send_timeout 3600; client_body_timeout 300; include /etc/nginx/mime.types; default_type application/octet-stream; log_format with_time '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" $request_time'; access_log /dev/stdout with_time; error_log stderr; gzip on; gzip_disable "msie6"; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/s; limit_req_status 429; }2. default.conf
default.conf# development upstream webserver { ip_hash; server back:8001; } map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 8000; server_name 127.0.0.1; client_header_buffer_size 1k; large_client_header_buffers 8 32k; add_header Strict-Transport-Security 'max-age=31536000'; add_header X-Frame-Options DENY; add_header X-XSS-Protection "1; mode=block"; error_page 500 502 503 504 /50x.html; # フロントエンド location / { root /var/www/front; try_files $uri $uri/ /index.html; } # バックエンドサーバー 静的ファイル群 location /static { alias /var/www/static; } # バックエンドサーバー location /back/ { include /etc/nginx/uwsgi_params; uwsgi_pass webserver; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; proxy_read_timeout 86400s; proxy_send_timeout 86400s; } # バックエンド adminサーバー location /admin/ { include /etc/nginx/uwsgi_params; uwsgi_pass webserver; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } location = /50x.html { root /usr/share/nginx/html; } }3. uwsgi_params
uwsgi_paramsuwsgi_param QUERY_STRING $query_string; uwsgi_param REQUEST_METHOD $request_method; uwsgi_param CONTENT_TYPE $content_type; uwsgi_param CONTENT_LENGTH $content_length; uwsgi_param REQUEST_URI $request_uri; uwsgi_param PATH_INFO $document_uri; uwsgi_param DOCUMENT_ROOT $document_root; uwsgi_param SERVER_PROTOCOL $server_protocol; uwsgi_param REQUEST_SCHEME $scheme; uwsgi_param HTTPS $https if_not_empty; uwsgi_param REMOTE_ADDR $remote_addr; uwsgi_param REMOTE_PORT $remote_port; uwsgi_param SERVER_PORT $server_port; uwsgi_param SERVER_NAME $server_name;問題ないかテスト
試しにVue.js側でAxiosを導入して、
リクエストを送ってみて、きちんとAPIサーバーから値が帰ってくるか、
確認してみます。1. Vue.js側のAxios通信の作成
試しにボタンからAPIサーバーへリクエストを送る処理を書いていきます。
戻り値を表示する部分も用意します。ターミナル$ docker-compose run front npm install -S axiosインストールしたAxiosをmain.jsにセッティングします。
main.jsimport Vue from 'vue' import App from './App.vue' import axios from 'axios' Vue.config.productionTip = false Vue.prototype.$axios = axios new Vue({ render: h => h(App), }).$mount('#app')初期作成されたHelloWorld.vueに追記していきます。
HelloWorld.vue<template> <div class="hello"> <h1>{{ msg }}</h1> <!-- 下記記載 --> <h2>ここに結果が表示されます → {{ result }}</h2> <button @click="getAPI()">クリック!</button> <p> For a guide and recipes on how to configure / customize this project,<br> check out the <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>. </p> <!-- ~~~ 割愛 ~~~ --> </template> <script> export default { name: 'HelloWorld', props: { msg: String }, // 下記記載 data () { return { result: 'No Result', url: 'http://localhost:8000/back/testapi/get/' } }, methods: { getAPI () { this.$axios.get(this.url) .then(response => { this.result = response.data.message }) } } } </script>2. Django側のレスポンス処理の作成
URLConfへの記載、Views.pyにてレスポンス処理を書いていきます。
今回はhello worldを返すようにします。root側のurls.pyfrom django.contrib import admin from django.urls import path urlpatterns = [ path('admin/', admin.site.urls), path('back/testapi', include('testapi.urls', namespace='testapi')), ]App側のurls.pyfrom django.urls import include, path from .views import * app_name = 'testapi' urlpatterns = [ path('get/', GetTestAPI.as_view()), ]views.pyfrom django.shortcuts import render from rest_framework import status, viewsets, filters from rest_framework import permissions from rest_framework.response import Response class GetTestAPI(APIView): permission_classes = (permissions.AllowAny,) def get(self, request, format=None): return Response(data={'status': 'Hello World!'}, status=status.HTTP_200_OK)settings.py# ~~ 省略 ~~ # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'testapi' ] # ~~ 省略 ~~3. 疎通
サーバーを立ち上げてブラウザ上から確認してみます。
$ docker-compose up -dまとめ
現在SPA+APIサーバー環境をDocker上で構築することで、
短い時間で、簡単に構築することができます。現在弊社では、HRモンスターと呼ばれる
採用の新しいスタイルを提供するサービスをローンチいたしました。ローンチ後のさらなる機能追加、改善などのPDCAサイクルを回すべく、
エンジニアを募集しております。
https://www.wantedly.com/projects/341182Kubernetes、Vue.js(Javascript)、Django(Python)といったモダンな技術を使って、
開発しておりますので、もしご興味がある方はぜひ、ご応募お待ちしております。