MVCモデル
記事作成の経緯
Railsでポートフォリオを作成している中で、そもそもMVCモデルを理解してないため、開発するときやエラーがあった際にどこから手をつければいいのか分からないことが多い。
そのため、そもそもMVCモデルが何なのかを理解し、どういった構成でプログラムが作られているのか理解するため、自分なりにまとめてみる。
MVCモデルとは
プログラムをModel,View,Controllerの3つの役割に分けた構成のこと
それぞれの役割は
Model
プログラムで扱われるデータを管理するView
画面の表示、画面からの入力を受け付けるController
ModelとViewを制御する
具体例
ECサイトで商品をカゴに入れる処理をした場合の処理の流れ
View
商品をカゴに入れる入力を受け付けるController
Viewの操作を受け取り、Modelに商品をカゴに入れるよう指示するModel
カゴに商品が追加される
MVCモデルによる利点
プログラムの構成を把握しやすくなる
特定のモデルに基づき開発をすることで、プログラムを初めて見る人がどこに何の役割をもつプログラムがあるか分かりやすくなる分業しやすい
デザイナーはView,プログラマーはControllerなど担当者に合った機能を任せることが出来る仕様変更しやすい
それぞれの機能が独立しているため、仕様変更の際に特定の箇所だけを修正するだけでいい
所感
いざ自分の言葉で説明すると自分の思っていたよりも理解していないことが分かった。
ただまとめると考えが整理されるため、理解が甘いことはまとめてみることを習慣にする。
また、ただその技術のことを理解するのではなく、その技術がある理由まで考えると納得して使うことが出来る。
参考
【Rails】バージョンを指定してプロジェクトを作成する
- インストール済みのrailsのバージョンを確認する
$ gem list -e rails *** LOCAL GEMS *** rails (6.0.1, 6.0.0, 5.2.1)
- インストール済みのバージョンを指定して
rails new
する
# 5.2.1を指定する場合 $ rails _5.2.1_ new app_name
- 指定したバージョンでプロジェクトが作成されていることを確認する
$ cd app_name $ rails -v Rails 5.2.1
なお、バージョン指定がない場合はインストールされている最新バーションでプロジェクトが作成される。 (今回の場合は6.0.1で作成される)
- 補足
railsの指定バージョンをインストールする方法
# 4.1.1をインストールする場合 $ gem i -v 4.1.1 rails
gitでリモートにpushするとerror: failed to push some refs toが表示される
環境
- macOS 10.14.6
- git 2.23.0
事象
ローカルブランチにfeature/#7_test
を作成し、コミット後にリモートへpushした際に以下エラーが発生
$ git push origin feature/#7_test Enumerating objects: 5, done. Counting objects: 100% (5/5), done. Delta compression using up to 4 threads Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 335 bytes | 335.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0) remote: Resolving deltas: 100% (1/1), completed with 1 local object. To https://github.com/seiya2130/git_tutorial.git ! [remote rejected] feature/#7_test -> feature/#7_test (cannot lock ref 'refs/heads/feature/#7_test': 'refs/heads/feature' exists; cannot create 'refs/heads/feature/#7_test') error: failed to push some refs to 'https://github.com/seiya2130/git_tutorial.git'
原因
- リモート追跡ブランチに
remotes/origin/feature
が残っていたため
ブランチ名で/(スラッシュ)が使われている場合、スラッシュ内で同名の単語があるとpush出来ない。
git branch -a
でブランチを確認すると、リモート追跡ブランチにremotes/origin/feature
があった。
$ git branch -a * feature/#7_test feature/test master remotes/origin/HEAD -> origin/master remotes/origin/feature remotes/origin/master remotes/origin/test
今回作成したブランチであるfeature/#7_test
のfeature
の部分が一致してしまい、pushが出来なかった
(同ディレクトリの中に同名フォルダが作れないようなイメージ)
対応
- 不要なリモート追跡ブランチを削除し、pushする
-
git remote prune orign
でリモートブランチを削除する -
git push origin feature/#7_test
で再度pushする
-
参考
Docker/Kubernetes実践コンテナ入門 復習(2)
Dockerコンテナのデプロイ
コンテナでアプリケーションを実行する
- Dockerイメージ
- Dockerコンテナを構成するファイルシステム、実行するアプリケーションをまとめた、コンテナを作成するテンプレートとなるもの
- Dockerコンテナ
- Dockerイメージから作成され、具現化されたファイルシステムとアプリケーションが実行されている状態
簡単なアプリケーションとDockerイメージを作る
- DockerfileにはDocker独自のDSL(ドメイン固有言語)で構成を定義する
FROMやRUNはインストラクション(命令)と呼ばれる
FROM
- Dockerイメージのベースイメージを指定
- 取得するイメージはDocker Hubというホスティングサービスに公開されているもの
- タグを指定することで特定のバージョンのイメージを識別する
RUN
- Dockerイメージビルド時にDockerコンテナ内で実行するコマンド
COPY
- Dockerを動作させているホストマシンのファイルやディレクトリをDockerコンテナ内にコピーする
CMD
- Dockerコンテナとして実行する際に、コンテナ内で実行するプロセスを指定
- RUNでアプリケーションの更新や配置、CMDでアプリケーションそのものを動かす
Dockerイメージをビルドする
- Dockerイメージを
docker image build
によりビルドする-
docker image build -t イメージ名[:タグ名] Dockerfileディレクトリパス
-
- -tオプションとイメージ名なしだとハッシュ値で管理ことになるため、必ずつける
- イメージ名の衝突回避のため、名前空間をつけることを推奨
example/test
ENTRYPOINTでコマンドの実行の仕方を工夫する
- ENTRYPOINTはCMDと同じくコンテナ内で実行するプロセスを指定可能
- CMDの引数がENTRYPOINTで実行するファイルへの引数となる
- コンテナの用途を制限したい場合に使用する
Dockerコンテナを実行する
docker container run Dokerイメージ
- -dオプションでバックグラウンド実行
ポートフォワーディング
- ホストマシンのポートをコンテナポートに紐付け、コンテナの外からきた通信をコンテナポートに転送する(コンテナポートは通常ホストからアクセス不可のため)
-p ホスト側ポート:コンテナポート
Dockerイメージの操作
- Dockerの基本操作はイメージに関する操作かコンテナに関する操作
- DockerイメージはDockerコンテナを作成するテンプレート
- DockerfileからDockerイメージを構築することをDockeイメージをビルドするという
docker image build イメージのビルド
- Dockerfileを元にDockerイメージを作成する
- -tオプションはイメージ名・タグ名子弟のため必須
- -fオプションはデフォルトのDockerfile以外のファイルを使う
- --pullオプションはFROMで指定したイメージをレジストリから取得する(取得ずみでもベースイメージを再取得する)
docker search イメージの検索
- Docker hubではリポジトリでDockerイメージを管理している
docker search オプション 検索キーワード
で登録リポジトリを検索可能- 表示はSTARSの降順
- --limit オプションで表示数制限
docker image pull イメージの取得
- Dockerレジストリからイメージを取得
docker image pull リポジトリ[:タグ名]
- タグを省略した場合、デフォルトのタグが利用される
docker image ls イメージの一覧
- ホストに保持されているイメージの一覧を表示する
docker image ls リポジトリ[:タグ名]
- docker pull/docker image buildしたイメージ
- コンテナIDとイメージIDは別物
docker image tag イメージのタグ付け
- Dockerイメージの特定のバージョンにタグ付けする
Dockerイメージのバージョン
- Dockerイメージのバージョン=イメージID(バージョン番号)
イメージIDへのタグ付け
- タグはイメージIDを持つDockerイメージを識別するためのもの
- タグを指定しない場合はlatestのタグがつく
- ビルド後のイメージにもタグ付け可能
docker image tag 元イメージ名 新イメージ名
docker image push イメージの公開
- DockerイメージをDoceker Hubに登録する
docker image push リポジトリ名:[タグ]
- 公開リポジトリのため、パスワードなどの機密情報は含めないようにする
Dockerコンテナの操作
Dockerのライフサイクル
- コンテナは実行中、停止、破棄の状態がある
- 作成されたコンテナは同じイメージを利用していても個別に状態を持つ
実行中
- Dockerイメージからコンテナが作成され、CMDやENTRYPONTで定義したアプリケーションの実行を開始する
- アプリケーションが実行中ならコンテナは実行中にある
停止
- 明示的に停止するかコンテナのアプリが終了した場合に自動停止する
- ディスクにコンテナの状態は残るため、再実行可能
破棄
- 停止したコンテナは明示的に破棄しない限りディスクに残り続けるため、不要なコンテナは破棄する
- 一度作成されたコンテナは開始時間などが異なるため、同じ状態のコンテナは作成不可
docker container run コンテナの作成と実行
- イメージからコンテンを作成・実行する
docker container run イメージ名/イメージID コマンド コマンド引数
- コンテナに名前をつけることで開発時の検証でコンテナIDやコンテナ名を頻繁に確認せずに済む
docker container run --name コンテナ名 イメージ名
docker contailer ls コンテナの一覧
- 実行中および終了したコンテナの一覧を表示
docker container ls
- -qオプションでコンテナIDだけ取得
- -filterオプションでイメージ名指定など特定のコンテナだけ取得
- -aオプションで終了したコンテナも含め取得
docker container stop コンテナの停止
- 実行しているコンテナを終了する
docker container stop コンテナIDまたはコンテナ名
docker container restart コンテナの再起動
- 停止したコンテンを再起動する
docker container restart コンテナIDまたはコンテナ名
docker container rm コンテナの破棄
- 停止したコンテナを削除する
docker container rm コンテナIDまたはコンテナ名
- -fオプションで実行中のコンテンを強制削除が可能
docker container run --rm
で停止後に自動削除する
docker container logs 標準出力の取得
- Dockerコンテナの標準出力を表示
- コンテナ内のアプリケーションがファイル出力したログは確認できない
docker container log コンテナIDまたはコンテナ名
docker container exec 実行中コンテナでコマンド実行
- 実行中コンテナで任意のコマンド実行
docker container exec コンテナID/コンテナ名 コンテナ内で実行するコマンド
docker container cp ファイルのコピー
- コンテナ同士、ホストとコンテナでファイルをコピーする
- 主にデバッグで使用する
docker container cp コピー元 コピー先
運用管理向けコマンド
prune 破棄
- 実行していないコンテナやイメージを一括削除する
docker container prune
docker image prune
docker container stats 利用状況の取得
- コンテナ単位のシステムリソースの利用状況を表示
Docker Composeでマルチコンテナを実行する
docker-composeによるコンテナの実行
- yaml形式の設定ファイルで複数コンテナの実行を管理できる
- Dockerイメージのビルドも行い、実行もできる
- イメージを頻繁に更新する開発時には--buildオプションをつけることでイメージのビルドが必ず実行される
Docker/Kubernetes実践コンテナ入門 復習(1)
Dockerの基礎
Dockerとは
- コンテナ仮想化技術を実現するために実行される常駐アプリケーションとそれを操作するためのコマンドフロントインターフェース
- ローカルで環境のセットアップが出来ていれば、コマンド一つで環境構築が可能
- 仮想マシンより高速でローカル・サーバー間で環境を簡単に再現出来る
Dockerの基礎概念
コンテナ型仮想化技術
- コンテナ型仮想化技術はDocker登場前はLXC(Linux Container)が有名だった
- コンテナ型仮想化技術では仮想化ソフトなしでOSのリソースを隔離し仮想OSとするためオーバヘッドが少ない
- 仮想化ソフトを利用する場合はホストOS型の仮想化と呼び、オーバヘッドが大きくなりがち
アプリケーションにフォーカスしたDocker
- LXCでは別のLXCホストで実行しようとしてもLXCの設定差異によって動作しない場合があったため、アプリケーションのデプロイ・運用の観点で機能不足だった
- Dockerはコンテナの情報をコードで管理することで取得・配布が容易で再現性が保ちやすいなど、アプリケーションのデプロイにフォーカスした機能を持っている
- Dockerはコンテナに実行環境とアプリケーションを同梱しているため、実行環境の依存問題を解決出来る
Dockerを利用する意義
環境際問題からの脱却
- サーバーの環境差異によって同じ挙動にならないことがあるため、環境際を限りなく排除する必要がある
Infrastructure Code Immutable Infrastructure
- Infrastructure Code
- コードベースでインフラを管理する
- 手作業を介する余地を減らすことで、同じ構成のサーバーを再現しやすくする
- ただし冪等性(何度実行しても同じ結果が保証される)を保ち続けることは難しい
- Immutable Infrastructure
- ある地点のサーバーの状態を保存し複製可能にする考え方
- 正しくセットアップされた状態を常に使うことが出来る
- 既存のインフラをアップデートするのではなく、新しく作り直すため、冪等性を気にする必要がない
アプリケーションとインフラをセットで構築する
- 旧来はインフラとアプリのデプロイは分断された作業だったため、環境差異が生まれやすかった
- コンテナはOS(インフラ)とアプリをセットでビルドできるため、環境差異が生まれにくい
- 作成したDockerイメージは保存、再利用が可能なためポータビリティが高い
アプリケーションの構成管理のしやすさ
- 一定の規模のシステムは複数のアプリやミドルウェアが組み合わさっているため、システム全体の構成管理が必要
Dockerのコンテナオーケストレーションシステム
- 複数コンテナを利用したアプリの管理のためにDocker Composeというツールがある
- yamlファイルで実行するコンテナを定義したり、依存関係を定義して起動順を制御する
- Docker Swarmは複数のサーバーをまたいで複数のコンテナを管理できる(コンテナオーケストレーション)
本番環境に導入してこそのDocker
新しい開発スタイルへ
- Dockerの普及でインフラがコードレベルで簡単に修正できるようになった
- インフラエンジニアとサーバーサイドエンジニアの垣根がなくなりつつある
- 現代的な開発のためにフロントエンドやスマホアプリエンジニアにも必要な技術になりつつある
入門docker 復習(8)
プロダクションでの活用
プロダクションへの導入
ローカル環境のDocker化
- チームの開発環境を統一する
テスト/CIへの導入
- ステージングへの導入
- 本番前に動作確認する
- 本番への導入
Tips
docker-compose
環境変数への読み込み
- docker-composeの起動時に渡す
docker-compose up -e MYSQL_PASSWORD=mypassword
- docker-compose.yamlへ記述
version: '3.7' services: app: build: . + environment: + - MYSQL_PASSWORD=mypassword
- シェル変数から読み込み
version: '3.7' services: app: build: . environment: - - MYSQL_PASSWORD=mypassword + - MYSQL_PASSWORD=${MYSQL_PASSWORD}
$ export MYSQL_PASSWORD=mypassword $ docker-compose up
- ファイルから読み込む
version: '3.7' services: app: build: . - environment: - - MYSQL_PASSWORD=mypassword + env_file: + - .env
#.env MYSQL_PASSWORD=mypassword
$ docker-compose up
ホストとコンテナ間のファイル共有の速度向上
オプション
consistend(default)
- ホストとコンテナ間の一貫性を担保するオプション
- オーバーヘッドが大きいため、ファイルの更新が発生する場合は非推奨
cached
- ホストの更新を優先する
- サービスコードのようにホスト側で更新するケース
delegated
- コンテナ側の更新を優先する
- MYSWLのようにコンテナからホストへの書き込みしかしないケース
- コンテナ上からライブラリのインストールをするコマンド(
composer install
,npm install
)を使用する場合
標準入力を有効にする
- デバッグに使用したい場合、明示的に設定可能
services: rails: build: . + tty: true + stdin_open: true ports: - '3000:3000' volumes: - './:/app:cached'
Multi-Stage Buildのローカル活用
- 過去のレイヤーを使用したい場合、明示的に設定可能
ersion: '3.7' services: app: build: context: . + target: build volumes: - ./:/go/app command: go run main.go
docker-compose間のnetworkの共有
- マイクロサービス化によってフロントとバックバックエンドでリポジトリが異なる場合がある
- ネットワークを共有する必要がある
backend
- internalとexternalのネットワークを用意する
version: '3.7' services: api: build: . ports: - 8000:80 + networks: + - internal + - external mysql: image: mysql:5.7 environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' + networks: + - internal +networks: + internal: + internal: true + external: + name: api_network
web
version: '3.7' services: web: #XXX APIアクセスはcurlで代用。 image: amazonlinux:2 command: curl api:80 +networks: + default: + external: + name: api_network
入門docker 復習(7)
プロダクションでの活用
オーケストレーションツール
オーケストレーションツールとは
- 複数のDockerを扱うための技術
- 主に以下の機能をもち、本番のワークロードに必要な機能を備えている
- Dockerの管理/自動復旧
- ネットワークの管理
- オートスケール
代表的なオーケストレーションツール
- docker-compose
- Docker社が所管するオーケストレーションツール
- ローカルでDockerを動かす際のデファクトスタンダードなツール
- Docker for Windows/Mac インストール時に同時にインストールされる
- swarm
- docker-composeと同じくDocker社所管ツール
docker-compose.yml
を拡張することで本番のワークロードでDockerを使用できる
- ECS(Elastic Container Service)
- AWSが開発したオーケストレーションツール
- 他のツールより責任範囲が狭いため、学習コストが低い
- Kubernetes
- Google社が開発したオーケストレーションツール
- 現在のデファクトスタンダート
docker-compose
概要
- docker-composeはローカルでDockerのオーケストレーションを行うツール
- DockerのビルドからNetworkやVolumeの管理をコードベースで定義して行う
サンプル
version: '3.7' services: nginx: build: context: . dockerfile: docker/nginx/Dockerfile volumes: - ./public:/var/www/html/public:ro ports: - 8080:80 environment: PHP_HOST: app app: build: context: . dockerfile: Dockerfile env_file: - .env.example # volumes: # - .:/var/www/html:cached mysql: image: mysql:5.7 volumes: - ./mysql:/var/lib/mysql:delegated command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' ports: - 13306:3306
version
- docker-composeのバーション
- こだわりがなければ最新を記述
services
- 起動するコンテナの定義
- ngix,app,mysqlを定義
image
- コンテンを起動するDockerImageを指定
build
- docker buildの実行情報
- この情報をもとにDockrをビルドし、ビルドしたイメージを使用してコンテナを起動する
- imageまたはbuildどちらかを記述
volumes
- ボリュームのマウントを行う
-
- ポートの解放を行う
- 左にホスト、右にコンテナのポートを指定する
environment
- 起動するコンテナへ環境変数を定義する
env_file
- ファイルに記載された環境変数を読み取り、コンテナに定義する
command
- Dockerfileで定義されているCMDの上書きを行う
docker-composeのコマンド
up
- カレントの
docker-compose.yaml
を参照してdocker-composeの起動docker-compose up
- カレントの
down
- カレントの
docker-compose.yaml
に紐づいているContainerとNetworkを削除docker-compose down
- イメージも削除
docker-compose down --rmi all
- カレントの
rm
- Volumeを削除
docker-compose rm
- Volumeを削除