- 投稿日:2020-01-10T22:07:34+09:00
Flask+MySQLで作るAPIをDocker化するまで
これは?
APIを作リたい。Flask+MySQLで作りたい。そしてDocker化したい。
この手順をメモとして残す。個人的にDocker化するところが良く分かっていないので、ここを集中的に。やること
- Flask単体で簡単なAPIを作る。
- 1をDocker化する。
- MySQLを用意する。
- FlaskとMySQLの連携をdocker-composeで実行できるようにする。
1. Flask単体で簡単なAPIを作る。
まずなんでもいいから単純なAPIを作る。今回は、会員リスト(仮)から条件にあうデータだけをリストにして返すものを作ることに決めた。
下のファイルから、prefectureがリクエストのパラメータと一致するmail_addressのリストを返却する機能を作る。
personal_info.csvmail_address,sex,age,name,prefecture hoge1@gmail.com,male,18,itirou,tokyo hoge2@gmail.com,male,23,zirou,osaka hoge3@gmail.com,male,31,saburou,tokyo hoge4@gmail.com,female,29,itiko,tokyo hoge5@gmail.com,mail,11,shirou,osaka hoge6@gmail.com,female,42,fumiko,tokyoFlaskを使ったコードはこちら。
超簡単で、app.pyを実行して、
http://127.0.0.1:5000/に?pref=xxxをつけると、pref=xxxに一致するmail_addressがリストで返却される。次は、このAPIをDocker化する。
2. 1をDocker化する。
「Docker化する」とは、Dockerfileを作ってdocker buildしてDocker imageを作り、docker runでコンテナ内でapp.pyを実行してAPIリクエストが投げられる状態を作ることを目指す。
Dockerfileとは、作りたいコンテナに対し、"ベースとなるイメージを指定し、作成するコンテナの設定を記述して、コンテナ内でコマンドを実行する"動作を記述するもの。
2-1 ベースとなるイメージを指定
pythonでflaskを実行できれば良いので、pythonのイメージをベースにする。
2-2 コンテナの設定を記述
flaskのコードを動かすためには、以下が必要。
- ローカルのソースコードやデータをコンテナに配置する。
- 必要なライブラリをinstallする。
2-3 コンテナ内でコマンドを実行する。
作成したapp.pyを実行する。
これら2-1~2-3を意識して作ったDockerfileが以下。
# 2-1 ベースとなるイメージを指定 FROM python:3.6 # 2-2 コンテナの設定を記述 ARG work_dir=/work # Dockerfile内で扱う変数の作成 ADD pure_flask $work_dir/pure_flask # コードを/work/にコピー(ディレクトリをコピーする時は、右側にディレクトリ名を記述しないといけないので注意) WORKDIR $work_dir/pure_flask # cd work_directoryのイメージ RUN pip install -r requirements.txt # requirements.txtで必要なライブラリをインストール # 2-3 コンテナ内でコマンドを実行 CMD ["python", "/work/pure_flask/app.py"] # CMDは基本的にDockerfile内に1つだけ。requirements.txtは超簡単にflaskだけ記述。
requirements.txtflaskこの状態のDockerfileがあるディレクトリで
docker build -t flask:ver1 .を実行する。
上記コマンドの.はカレントディレクトリにあるDockerfileを使ってイメージをbuildすることを指す。次に、
docker run -it -d -p 5000:5000 flask:ver1を実行。
-dはバックグラウンド実行を、-p 5000:5000はローカルの5000番ポートと、コンテナの5000番ポートのポートフォワーディングを指定することを指してます。この状態でローカルマシンでlocalhost:5000でブラウザで確認すると、APIのreturnが確認できる。
ちなみにこの状態で
docker psとdocker imagesは以下のようになる。
もしdocker psで何も表示されない場合はエラーでこけてる可能性があるため、docker ps -aで表示したコンテナIDを使って、docker logs [コンテナID]をしてあげると理由がわかるかも。$ docker ps > CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES > dc371c597cef flask:ver1 "python /work/pure_f…" 9 minutes ago Up 9 minutes 0.0.0.0:5000->5000/tcp quizzical_margulis $ docker images > REPOSITORY TAG IMAGE ID CREATED SIZE > flask ver1 b4cda0e56563 9 minutes ago 923MB > python 3.6 138869855e44 5 days ago 913MB無事、1. Flask単体で簡単なAPIを作ると同じ動作がDocker上でも確認できた。
次は、MySQLを使うための準備をする。
3. MySQLを用意する。
MySQLもDockerで用意する。今回は、Docker-compose.yamlの利用も同時にする。
Docker-compose.yamlは、Dockerfileと似ているが、複数のコンテナの連携などを記述するためにある。
DBは接続されることが前提のため、Docker-composeで記述するのが自然だと思う。3-1 ベースとなるイメージを指定
MySQLが使いたいため、MySQLのイメージをベースにする。
3-2 コンテナの設定を記述
MySQLの設定ファイルやデータベースの初期化をする。
3-3 コンテナ内でコマンドを実行する。
MySQLのプロセスを起動する。
Dockerfileは以下。
# 3-1 ベースとなるイメージの指定 FROM mysql:5.7 # 3-2 コンテナの設定を記述 COPY conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf # 文字コードの設定のセット COPY initdb.d/init.sql /docker-entrypoint-initdb.d/init.sql # 初期化用のSQLファイルのセットDockerfileの中でcopyしているconfigファイルとinit.sqlはそれぞれ以下。
mysql.cnf[mysqld] character-set-server=utf8 [mysql] default-character-set=utf8 [client] default-character-set=utf8init.sqlCREATE TABLE `personal_info` ( mail_address VARCHAR(100) NOT NULL, sex VARCHAR(6) NOT NULL, age INT NOT NULL, name VARCHAR(50) NOT NULL, prefecture VARCHAR(50) NOT NULL, createdAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updatedAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (mail_address) ); INSERT INTO `personal_info` (mail_address, sex, age, name, prefecture, createdAt, updatedAt) VALUES ('hoge1_1@gmail.com', 'male', 18, 'ichirou1' , 'tokyo', current_timestamp(), current_timestamp()), ('hoge2@gmail.com', 'male', 23, 'zirou2', 'osaka', current_timestamp(), current_timestamp()), ('hoge3_3@gmail.com', 'male', 31, 'saburou', 'tokyo', current_timestamp(), current_timestamp()), ('hoge4@gmail.com', 'female', 29, 'itiko', 'tokyo', current_timestamp(), current_timestamp()), ('hoge5_5@gmail.com', 'mail', 11, 'shirou', 'osaka', current_timestamp(), current_timestamp()), ('hoge6@gmail.com', 'female', 42, 'fumiko', 'tokyo', current_timestamp(), current_timestamp());docker-compose.yamlは以下。
version: '3' # docker-compose.yamlの記述のバージョン services: db: build: mysql # mysqlディレクトリ配下のDockerfileを指定 container_name: db_server # Dockerコンテナの名前 ports: - '3306:3306' # ポートフォワーディング指定 environment: # 環境変数の設定 MYSQL_ROOT_PASSWORD: pass # MySQLのrootユーザーのパスワード MYSQL_DATABASE: testdb # MySQLのスキーマ TZ: Asia/Tokyo # タイムゾーンの指定 volumes: # MySQLのデータの永続化をするためのボリュームマウント - db-data/:/var/lib/mysql # 3-3 コンテナ内でコマンドを実行する command: mysqld # mysqldコマンドの実行 volumes: db-data:上記ができたら、
docker-compose up -dでdbコンテナを起動する。
その後、docker exec -it [コンテナID] /bin/bashでログインし、mysql -u root -pからパスワードを入力してテーブルを確認し、init.sqlの内容が入っていればOK。[備考]mysql周りのtips
MySQLのデータを永続化させるためのvolumeにデータが保存されない場合、Dockerホストでdocker volume lsでvolumeを確認して削除してからdocker-compose up -dすると良さげ。
init.sqlは/docker-entrypoint-initdb.d/に固定でコピーする。
次は、flaskとMySQLを接続させる。
4. FlaskとMySQLの連携をdocker-composeで実行できるようにする。
2と4で作成した二つのDockerコンテナを結合させる。
結合させるために必要なことは、以下。
- flaskもdocker-compose.yamlに入れる。
- flaskからMySQLへの接続が可能なようにする(ネットワークを)。
- flaskからMySQLへの接続が可能なようにする(コードを)。
4-1 flaskもdocker-compose.yamlに入れる
flaskのコンテナをMySQLのdocker-compose.yamlに追記したものは以下。
version: '3' services: api: build: python container_name: api_server ports: - "5000:5000" tty: yes environment: TZ: Asia/Tokyo FLASK_APP: app.py depends_on: # apiサーバーはdbサーバーが立ってから起動 - db networks: # apiとdbを接続するための共通ネットワーク指定 - app_net db: build: mysql container_name: db_server ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: pass MYSQL_DATABASE: testdb TZ: Asia/Tokyo volumes: - ./db-data:/var/lib/mysql command: mysqld networks: - app_net volumes: db-data: networks: app_net: driver: bridgeservices直下の階層に、dbと同じ階層としてapiを記述。
4-2 flaskからMySQLへの接続が可能なようにする(ネットワークを)。
コンテナを二つ起動し、その間で接続をする場合、二つのコンテナを同一のネットワークで扱う必要がある。
4-1のdocker-compose.yaml内にそれぞれのserviceの中に以下を追記する。networks: - app_netこれにより、各コンテナがどのネットワークを利用するかを指定できる。二つを同じネットワークにしていることを意味する。
そして、docker-compose.yamlのトップレベルの階層に以下を記述する。networks: app_net: driver: bridgeこれは、dockerのネットワークの作成を意味していて、driverをbridge指定で作る指定。
これでapiとdbのコンテナが同一ネットワーク上となるため、apiからdbへの接続が可能となる。4-3 - flaskからMySQLへの接続が可能なようにする(コードを)。
flask側のコードとモジュールの修正。
pythonからMySQLに接続する方法は色々ありそうだが、今回はmysqlclientを使った。
pip install mysqlclientでmysqlclientをインストールし、以下のようなコードで接続して使う。import MySQLdb conn = MySQLdb.connect(user='root', passwd='pass', host='db_server', db='testdb') cur = conn.cursor() sql = "select * from personal_info;" cur.execute(sql) rows = cur.fetchall()このrowsには、タプルが返却され、レコード数の長さのタプルが取得できる。
rowsのイメージ.( (1レコード目の1カラム目の値, 1レコード目の2カラム目の値, ...), (2レコード目の1カラム目の値, 2レコード目の2カラム目の値, ...), (3レコード目の1カラム目の値, 3レコード目の2カラム目の値, ...) )これをpythonで受け取り、リストに格納してjsonで返却するようなイメージ。
修正後のソースはここ。
ディレクトリ構成とか、Dockerfileの位置などもこれを参照してもらえれば。あとは、pythonで扱いたいモジュールが増えたのでrequirements.txtにmysqlclientを追記する。
これで完了。
docker-compose up -dで全て起動したら、ローカルでhttp://0.0.0.0:5000/?pref=osakaなどを入れると、結果が確認できる。以上。
- 投稿日:2020-01-10T22:02:52+09:00
Dockerで環境構築する際、ソースコードの変更が即時反映されない場合の対処法
記事の目的
docker-composeで環境構築する際に起こったRailsのソースコードを修正しても即時反映されない問題に対しての対処法を共有すること。
対処法
1.development.rbを編集
開発環境用の設定ファイルである
config/environments/development.rbを編集。
「 ~ 」は元々の記述を省略しているものとする。
この中にconfig.reload_classes_only_on_change = falseという記述を追加する。development.rbRails.application.configure do ~ config.reload_classes_only_on_change = false end2.railsコンテナを再起動
設定を記載しただけでは反映されないので、最後にRailsを再起動する。
ターミナル上で、
$ docker-compose restartと入力する。
以上でソースコードの変更が即時反映される。
終わりに
Dockerで環境構築をした際に、もう設定しておくと良い。
- 投稿日:2020-01-10T18:33:24+09:00
GitLabをDocker+Apacheでサブディレクトリ運用する
はじめに
OSSのGitリポジトリマネージャGitLabをDockerのコンテナ上で運用します
サブディレクトリで運用し,https://example.com/gitlab みたいなURLからアクセスできるようにします構成
- Apacheでwebブラウザからの接続を受け,リバースプロキシでlocalhost:3000にHTTP接続
- HTTPSを使う場合でも,ApacheでHTTPS接続を終端
- Dockerで3000番ポートからコンテナの80番ポートに接続
これにより,システムの環境とGitLabの環境をコンテナで分離して運用できます
また,ApacheでHTTPS接続を終端するので,GitLab側で余計な設定が不要になります環境
- Debian 9.11
- Apache 2.4.25
- Docker 1.13.1
- docker-compose 1.16.1
- GitLab 12.5.0
前提条件
ApacheやDocker, docker-composeのインストール及び基本的な設定は完了している事
HTTPSを使うならその設定も手順
1.Dockerのコンテナを作成
- 以下の内容で
docker-compose.ymlを作成し,コンテナを起動します- ポート番号は3000で最低限の設定を記述
- 3000 や example.com とした箇所は必要に応じて書き換えてください
docker-compose.ymlweb: image: 'gitlab/gitlab-ce:12.5.0-ce.0' restart: 'always' hostname: 'example.com' environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://example.com/gitlab' ports: - '3000:80' volumes: - '/srv/gitlab/config:/etc/gitlab' - '/srv/gitlab/logs:/var/log/gitlab' - '/srv/gitlab/data:/var/opt/gitlab'$ sudo docker-compose up -d2.Apacheでリバースプロキシの設定を追加
- 以下の内容で
/etc/apache2/sites-available/gitlab.confを作成し,設定を有効にします/etc/apache2/sites-available/gitlab.conf<Location /gitlab> ProxyPass http://127.0.0.1:3000/gitlab/ nocanon ProxyPassReverse http://127.0.0.1:3000/gitlab/ Header edit Location ^http:// https:// </Location>$ sudo a2ensite gitlab.conf & sudo systemctl reload apache2動作確認
- 以上の設定で https://example.com/gitlab からGitLabにアクセスできるはずです
- コンテナの再起動直後はProxy Errorや502が表示されますが,数分でアクセスできるようになります
その他
- GitLabの設定ファイルは
/srv/gitlab/config/gitlab.rbから編集可能- 変更後は以下のコマンドでコンテナに入り,GitLabを再構成します
$ sudo docker exec -it kaizawa_web_1 bash # gitlab-ctl reconfigure参考
GitLab Docker images | GitLab
ApacheやNginxでHTTPS通信をリバースプロキシする - grep Tips *
- 投稿日:2020-01-10T17:50:35+09:00
AWS CodePipelineでgoアプリのDockerイメージをECRに格納する
実現したいこと
- CodeCommitのリポジトリ(hoge-repo)のmasterブランチの更新をトリガーに
masterブランチのリソースからDockerイメージを作成しECRの対象リポジトリに格納したい- hoge-repoはgolangのアプリを持っているので,イメージ作成時にアプリのビルドも行う
環境
- Golang 1.13.5
- Docker 18
- AWS 東京リージョン
やったこと
CodeBuild構築
プロジェクト名は任意の名前
送信元
送信元はCodeCommitの対象リポジトリを選択今回はmasterマージをトリガーにするのでリファレンスタイプはブランチ
対象ブランチはmasterを指定
環境
Build環境は特に制限がなかったのでaws/codebuild/amazonlinux2-x86_64-standard:2.0を選択
残りの環境設定はデフォルトBuildspec
Buildspecファイルを使用するを選択
buildspec.yamlは後ほどアーティファクト
今回はDockerイメージのpushまでで,実際にEKSでコンテナの立ち上げまで行わないので
アーティファクトはなしを選択ログ
ログの監視も今回は行わないCodeBuildの権限追加
今回はCodeCommitからソースをダウンロードし,ECRにイメージプッシュするため
CodeBuildのサービスロールに以下ポリシーを付与
AWSCodeCommitReadOnlyAccess
AmazonEC2ContainerRegistryFullAccess
buildspec.yml作成
codebuildでデフォルト設定にしたので hoge-repoのルートディレクトリにbuildspec.ymlを配置
hoge-repo | |-- buildspec.yml |-- Makefile |-- Dockerfile |-- main.go ...buildspec.yaml
version: 0.2 phases: install: runtime-versions: docker: 18 commands: # ECRにイメージプッシュするためにログインする - $(aws ecr get-login --no-include-email --region ap-northeast-1) pre_build: commands: # go test -v -cover ./... - make test build: commands: # go build -v . - make build post_build: commands: # docker tag \code-commit-repo-name\:latest \erc-repo-name\:latest # docker push \erc-repo-name\:latest - make push-imageCodePipeline構築
CodePipelineの新規作成
パイプラインの設定
パイプライン名は任意の値を入力し,残りはデフォルトソースステージ
ソースプロバイダにAWS CodeCommitのhoge-repo masterブランチを選択
検索はAmazon CloudWatch Eventsを選択ビルドステージ
AWS CodeBuildの先ほど作成したプロジェクトを選択
今回環境変数は使用しないので残りはそのままデプロイステージ
実際にコンテナを立ち上げないのでデプロイステージはスキップする完成
ここまでの設定でCodeCommitのmasterブランチの更新をトリガーに
GoアプリがビルドされたDockerイメージを作成し,ECRにプッシュする構成ができた.この後
Pipeline実行する毎に goモジュール(外部ライブラリ)をダウンロードするのはイケてない(5分ぐらいかかる)
一度ダウンロードしたモジュールはキャッシュしておきたい(この後盛大にハマる)
- 投稿日:2020-01-10T17:38:28+09:00
Universal Base Images (UBI) 8 を日本語ロケールにする
配布されている Universal Base Images (UBI) 8 のロケールは C.utf8 ですが、用途によっては日本語ロケール ja_JP.utf8 で使用したいことがあります。そこで、UBI 8 を日本語ロケールにする方法を調べてみました。
ここで扱うのは、UBI 8 で UBI minimal ではありません。まずは、調査してみる
docker run --rm -it registry.access.redhat.com/ubi8/ubi:latest bashで起動して、淡い期待をもってlocale -aを実行してみましたが、やはり最初から日本語ロケールが組み込まれているということはありませんでした。C:\>docker run --rm -it registry.access.redhat.com/ubi8/ubi:latest bash [root@61670851e75a /]# locale -a C C.utf8 POSIX次に、利用できる langpacks をサーチしてみましたが、提供されているのは英語のものだけです。
glibc-all-langpacks.x86_64がありますが、これを インストールしてもロケールは追加されませんでした。[root@61670851e75a /]# dnf search langpacks Updating Subscription Management repositories. Unable to read consumer identity This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register. Last metadata expiration check: 0:02:02 ago on Fri Jan 10 07:24:31 2020. ========================================================= Name & Summary Matched: langpacks ========================================================== langpacks-en.noarch : English langpacks meta-package langpacks-en.noarch : English langpacks meta-package ============================================================== Name Matched: langpacks =============================================================== glibc-all-langpacks.x86_64 : All language packs for glibc.locale でサーチすると、いくつかパッケージが見つかりました。
glibc-common.x86_64をインストールすると、en_XX 系のロケールはインストールできましたが、日本語は追加されません。
残るは、glibc-locale-source.x86_64なるパッケージです。source とあるので、これを使って日本語ロケールを定義することにします。[root@61670851e75a /]# dnf search locale Updating Subscription Management repositories. Unable to read consumer identity This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register. Last metadata expiration check: 0:17:23 ago on 2020年01月10日 07時24分31秒. =========================================================== Name & Summary Matched: locale =========================================================== glibc-locale-source.x86_64 : The sources for the locales perl-Encode-Locale.noarch : Determine the locale encoding perl-Locale-Codes.noarch : Distribution of modules to handle locale codes perl-Locale-Maketext-Simple.noarch : Simple interface to Locale::Maketext::Lexicon ================================================================ Name Matched: locale ================================================================ perl-Locale-Maketext.noarch : Framework for localization ============================================================== Summary Matched: locale =============================================================== glibc-langpack-en.x86_64 : Locale data for en glibc-common.x86_64 : Common binaries and locale data for glibc glibc-common.x86_64 : Common binaries and locale data for glibc日本語ロケールを組み込む
dnf install -y glibc-locale-sourceで source をインストールし、localedef で日本語ロケールを定義することで、日本語ロケールが使用できるようになりました。
手順は以下の通りですが、分かってしまうと簡単ですね。C:\>docker run --rm -it registry.access.redhat.com/ubi8/ubi:latest bash [root@0f88101d5c72 /]# dnf install -y glibc-locale-source (出力は省略) [root@0f88101d5c72 /]# localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 [root@0f88101d5c72 /]# locale -a C C.utf8 POSIX ja_JP.utf8 [root@0f88101d5c72 /]# echo LANG=ja_JP.UTF-8 > /etc/locale.conf [root@0f88101d5c72 /]# export LANG=ja_JP.UTF-8 [root@0f88101d5c72 /]# date 2020年 1月 10日 金曜日 07:53:26 UTCタイムゾーンを変更する
dateコマンドの出力を見て、タイムゾーンの変更が必要なことを思い出しました。
まずは、調査ですが、zoneinfo を確認してみると、各地域のゾーン情報(tzdata)が入っていて、Asia/Tokyo もありました。[root@0f88101d5c72 /]# ls /usr/share/zoneinfo/ Africa Atlantic Canada EST5EDT GB GMT0 Indian Kwajalein Mexico PST8PDT ROK UTC iso3166.tab tzdata.zi America Australia Chile Egypt GB-Eire Greenwich Iran Libya NZ Pacific Singapore Universal leapseconds zone.tab Antarctica Brazil Cuba Eire GMT HST Israel MET NZ-CHAT Poland Turkey W-SU posix zone1970.tab Arctic CET EET Etc GMT+0 Hongkong Jamaica MST Navajo Portugal UCT WET posixrules Asia CST6CDT EST Europe GMT-0 Iceland Japan MST7MDT PRC ROC US Zulu right [root@0f88101d5c72 /]# ls /usr/share/zoneinfo/Asia/Tokyo /usr/share/zoneinfo/Asia/Tokyoタイムゾーンは、普通の方法で変更するだけで済みました。
[root@0f88101d5c72 /]# ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime [root@0f88101d5c72 /]# export TZ=Asia/Tokyo [root@0f88101d5c72 /]# date 2020年 1月 10日 金曜日 17:03:05 JST日本語ロケールにしたイメージをビルドする
手順が分かったので、Dockerfile を作ってイメージをビルドします。以下のような Dockerfile にしてみました。
FROM registry.access.redhat.com/ubi8/ubi:latest RUN dnf update -y \ && dnf install -y glibc-locale-source \ && localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 \ && echo LANG=ja_JP.UTF-8 > /etc/locale.conf \ && dnf remove -y glibc-locale-source \ && dnf clean all \ && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime ENV LANG="ja_JP.UTF-8" \ TZ="Asia/Tokyo"ビルドして確認してみます。
C:\ubi-jp>docker build -t ubi8-jp . Sending build context to Docker daemon 2.048kB (省略) Successfully tagged ubi8-jp:latest (省略) C:\ubi-jp>docker run --rm -it ubi8-jp bash [root@143587d7dbf8 /]# date 2020年 1月 10日 金曜日 17:09:51 JST [root@143587d7dbf8 /]# ls -al total 60 drwxr-xr-x 1 root root 4096 1月 10 17:09 . (省略) drwxr-xr-x 1 root root 4096 12月 11 02:50 var [root@143587d7dbf8 /]# sss bash: sss: command not found [root@143587d7dbf8 /]#最後に
UBI 8 を日本語ロケールに変更することができました。
詳細は触れませんが、UBI-minimal 8 や UBI 7 でもチャレンジしてみました。UBI-minimal 8 は、UBI 8 と同じ方法で日本語ロケールを追加できました。但し、localedef が使用する gzip が入っていないので、追加する必要があります。
さらに、ゾーン情報(tzdata)は自力で追加する必要がありました。microdnf install -y tzdataで追加したいところですが、インストール後に不要なものを rm コマンドで削除しているようで、microdnf install -y tzdataを実行しても追加できませんでした。
rpm パッケージをダウンロードして rpm2cpio と cpio -idv を使って力ずくで追加するしか方法がなさそうでした。microdnf install -y cpio curl https://cdn-ubi.redhat.com/content/public/ubi/dist/ubi8/8/x86_64/baseos/os/Packages/t/tzdata-2019c-1.el8.noarch.rpm | rpm2cpio | cpio -idv ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime microdnf remove -y cpio
- 投稿日:2020-01-10T17:08:32+09:00
Nexus RepositoryのOrientDBを復旧させた話
概要
- Nexus Repositoryで500エラーが返ってくるようになり、OrientDbを再作成して復旧させた
環境
- sonatype Nexus Repository Manager 3.4.0
- docker
- linux
発端
- Nexusへのファイルアップロードが突然できなくなった。
- 起動はしているのに、アップロードができない。
[INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 6.339 s [INFO] Finished at: 2020-01-06T01:30:50Z [INFO] Final Memory: 10M/239M [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy-file (default-cli) on project standalone-pom: Failed to deploy artifacts: Could not transfer artifact jp.hoge.fuga:api:jar:1.0.1-20200106.013045-1 from/to remote-repository (https://example.com/nexus/repository/maven-api-snapshots/): Failed to transfer file: https://example.com/nexus/repository/maven-api-snapshots/jp/hoge/fuga/api/1.0.1-SNAPSHOT/api-2.10.1-20200106.013045-1.jar. Return code is: 500, ReasonPhrase: Server Error. -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
- ログを見ると、中で使っているDB(OrientDB)でエラーとなっている
2020-01-06 01:30:44,913+0000 WARN [qtp637974386-634] admin org.sonatype.nexus.repository.httpbridge.internal.ViewServlet - Failure servicing: PUT /nexus/repository/maven-api-snapshots/jp/hoge/fuga/api/1.0.1-SNAPSHOT/api-2.10.1-20200106.013045-1.jar com.orientechnologies.orient.core.exception.OStorageException: Error during transaction commit DB name="component" 2020-01-06 01:30:44,913+0000 ERROR [qtp637974386-621] admin com.orientechnologies.orient.core.storage.impl.local.paginated.OLocalPaginatedStorage - $ANSI{green {db=component}} Exception `6C3A2748` in storage `component` java.lang.NullPointerException: nullやったこと
- 同じような事象に陥っている方の記事があったので、この通りにOrientDBの復旧を試してみたが…
# docker-compose run --rm nexus_service sh sh-4.2$ sh-4.2$ java -version sh: java: command not found
- 何と、当該バージョンのNexusには、javaがインストールされていなかった…
- ということで、一旦上記記事の方と同じバージョン(3.12.0)にアップデートした上で、OrientDBの復旧手順をやってみた
# docker-compose run --rm nexus_service sh sh-4.2$ sh-4.2$ java -version java version "1.8.0_172" Java(TM) SE Runtime Environment (build 1.8.0_172-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode) sh-4.2$ sh-4.2$ # ↑よかった、javaがインストールされている!! sh-4.2$ sh-4.2$ whoami nexus sh-4.2$ sh-4.2$ pwd / sh-4.2$ cd /opt/sonatype/nexus/ sh-4.2$ sh-4.2$ java -jar ./lib/support/nexus-orient-console.jar OrientDB console v.2.2.34 (build f340442755a31eabc91b87cb3ef99eda5cee6ebd, branch 2.2.x) https://www.orientdb.com Type 'help' to display all the supported commands. orientdb> ### 以下コマンドのみ、結果略 ### orientdb> CONNECT 'plocal:/nexus-data/db/analytics' admin admin orientdb> EXPORT DATABASE analytics-export orientdb> DROP DATABASE orientdb> CREATE DATABASE 'plocal:/nexus-data/db/analytics' orientdb> IMPORT DATABASE analytics-export.json.gz orientdb> DISCONNECT orientdb> exit sh-4.2$ exit # # コンテナ再起動 # docker-compose down # docker-compose up -d
- 無事復旧できた。
- 今回壊れていたのはcomponent DBのみだったので、他のDBの再作成は行っていない。
原因
- いまだに不明。
失敗したこと
- Nexus3.4.0でjavaがインストールされていなかったので、自力でインストールして上記手順を実施したところ、root実行してしまったため、コンテナ起動時にPermissionエラーが出続けてしまい立ち上がらなくなってしまった。
参考
- 投稿日:2020-01-10T14:40:32+09:00
[備忘録]dockerでjava環境を一から作る
DockerHubにあるjava環境イメージをpullしたら早いのに、一から作らないと落ち着かない損な性格なので作ってみた備忘録です。
環境
- macOS Catalina
- Docker Desktop for Mac (インストール済)
手順
1. ubuntuイメージ取得
$ docker pull ubuntu2. ubuntuコンテナ起動
$ docker run -it ubuntu bash以降はubuntuでの作業
3. apt-getコマンドの更新
$ apt-get update4. 最低限必要なコマンドをインストール
curlコマンド
$ apt-get install curlunzipコマンド
$ apt-get install unzipzipコマンド
$ apt-get install zip5. sdkmanのインストール
$ curl -s "https://get.sdkman.io" | bash$ source "/root/.sdkman/bin/sdkman-init.sh"確認
$ sdk help ==== BROADCAST ================================================================= * 2020-01-08: Asciidoctorj 2.2.0 released on SDKMAN! #asciidoctorj * 2020-01-07: Gradle 6.1-rc-2 released on SDKMAN! #gradle * 2020-01-06: Jbang 0.4.0.1 released on SDKMAN! #jbang ================================================================================ Usage: sdk <command> [candidate] [version] sdk offline <enable|disable> commands: install or i <candidate> [version] [local-path] uninstall or rm <candidate> <version> list or ls [candidate] use or u <candidate> <version> default or d <candidate> [version] current or c [candidate] upgrade or ug [candidate] version or v broadcast or b help or h offline [enable|disable] selfupdate [force] update flush <broadcast|archives|temp> candidate : the SDK to install: groovy, scala, grails, gradle, kotlin, etc. use list command for comprehensive list of candidates eg: $ sdk list version : where optional, defaults to latest stable if not provided eg: $ sdk install groovy local-path : optional path to an existing local installation eg: $ sdk install groovy 2.4.13-local /opt/groovy-2.4.13SDKMANのインストールは終わり
6. javaのインストール
インストールできるjavaを確認
$ sdk list java ================================================================================ Available Java Versions ================================================================================ Vendor | Use | Version | Dist | Status | Identifier -------------------------------------------------------------------------------- AdoptOpenJDK | | 13.0.1.j9 | adpt | | 13.0.1.j9-adpt | | 13.0.1.hs | adpt | | 13.0.1.hs-adpt | | 12.0.2.j9 | adpt | | 12.0.2.j9-adpt | | 12.0.2.hs | adpt | | 12.0.2.hs-adpt | | 11.0.5.j9 | adpt | | 11.0.5.j9-adpt | >>> | 11.0.5.hs | adpt | installed | 11.0.5.hs-adpt | | 8.0.232.j9 | adpt | | 8.0.232.j9-adpt | | 8.0.232.hs | adpt | | 8.0.232.hs-adpt Amazon | | 11.0.5 | amzn | | 11.0.5-amzn | | 8.0.232 | amzn | | 8.0.232-amzn Azul Zulu | | 13.0.1 | zulu | | 13.0.1-zulu | | 12.0.2 | zulu | | 12.0.2-zulu | | 11.0.5 | zulu | | 11.0.5-zulu | | 10.0.2 | zulu | | 10.0.2-zulu | | 9.0.7 | zulu | | 9.0.7-zulu | | 8.0.232 | zulu | | 8.0.232-zulu | | 7.0.242 | zulu | | 7.0.242-zulu | | 6.0.119 | zulu | | 6.0.119-zulu Azul ZuluFX | | 11.0.2 | zulufx | | 11.0.2-zulufx | | 8.0.202 | zulufx | | 8.0.202-zulufx BellSoft | | 13.0.1 | librca | | 13.0.1-librca | | 12.0.2 | librca | | 12.0.2-librca | | 11.0.5 | librca | | 11.0.5-librca | | 8.0.232 | librca | | 8.0.232-librca GraalVM | | 19.3.0.r11 | grl | | 19.3.0.r11-grl | | 19.3.0.r8 | grl | | 19.3.0.r8-grl | | 19.3.0.2.r11 | grl | | 19.3.0.2.r11-grl | | 19.3.0.2.r8 | grl | | 19.3.0.2.r8-grl | | 19.2.1 | grl | | 19.2.1-grl | | 19.1.1 | grl | | 19.1.1-grl | | 19.0.2 | grl | | 19.0.2-grl | | 1.0.0 | grl | | 1.0.0-rc-16-grl Java.net | | 15.ea.4 | open | | 15.ea.4-open | | 14.ea.30 | open | | 14.ea.30-open | | 13.0.1 | open | | 13.0.1-open | | 12.0.2 | open | | 12.0.2-open | | 11.0.5 | open | | 11.0.5-open | | 10.0.2 | open | | 10.0.2-open | | 9.0.4 | open | | 9.0.4-open | | 8.0.232 | open | | 8.0.232-open SAP | | 12.0.2 | sapmchn | | 12.0.2-sapmchn | | 11.0.4 | sapmchn | | 11.0.4-sapmchn ================================================================================ Use the Identifier for installation: $ sdk install java 11.0.3.hs-adpt ================================================================================インストールしたいjavaを指定
$ sdk install java 8.0.232-open確認
root@d9b652b0db21:/# java -version openjdk version "1.8.0_232" OpenJDK Runtime Environment (build 1.8.0_232-b09) OpenJDK 64-Bit Server VM (build 25.232-b09, mixed mode)以上で、DockerにJava環境を作りました。
あとは煮るなり焼くなり。
- 投稿日:2020-01-10T14:32:34+09:00
manjaroブート時にdocker deamonを起動する
sudo systemctl enable docker
- 投稿日:2020-01-10T13:59:38+09:00
Railsで開発した個人アプリにDockerを導入する手順と最低限の知識
Railsで開発した個人アプリに、後からDockerを導入しました。
その時知識不足なせいでハマってしまった場面があったので、自分の中で整理してアウトプットすることを目的にこの記事を書き残します。ちなみに、以下の記事を主に参考にさせていただきました。
DockerをMacにインストールする
Docker + Rails + Puma + Nginx + MySQLRailsアプリにDockerを導入する手順+事前知識
まずは事前知識として、これは知っておいたほうがいいというものを簡単に書いていきます。
事前知識 - Docker関係
Docker(ドッカー)
※1.軽量な仮想化環境を実現するためのツール。
OS やアプリケーションを設定したものを丸ごと実行イメージとして保存できるので、Docker が導入されている別のマシンにそのまま持って行くことができる。
実行環境をテキストファイルとして共有できるのでとても便利。
※1.仮想化環境とは、コンピュータ上にソフトウェアによって仮想的に構築されたコンピュータ(仮想マシン)が備える仕様や機能の総体のこと。
Dockerイメージ
Dockerイメージは、コンテナを起動させるためのベースとなるもの(オブジェクト指向でいうと「クラス」にあたる)
テキストファイル(Dockerfile)からビルドされる。(後に記述)
DockerHub(Docker向けのコンテナ共有サービス)では、既に多くのイメージが公開されている。
Dockerコンテナ
Dockerのコンテナは、 Dockerイメージを元に作成される仮想環境の実行部分(オブジェクト指向でいうと「インスタンス」にあたる)
原則1コンテナ1アプリ。
Dockerfile(ドッカーファイル)
指定したベースのDockerイメージに加える変更を記述するファイル。
Dockerfileを使うことでオリジナルのDockerイメージを作成することができる。
docker-compose(ドッカーコンポーズ)
複数のコンテナから構成されるアプリケーションで、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするツール。
docker-composeを使用する際は「docker-compose.yml」が必要になる。
事前知識 - サーバ関係
ミドルウェア
OSとアプリケーションの間に入り、中間的な処理を行うソフトウェアのこと。
ー 例 ー
- Webサーバ
- Apache、NginXなど
- APサーバ
- Puma
- Unicornなど
- DBサーバ
- MySQL
- PostgreSQLなど
Nginx(エンジンエックス)
webサーバの一つ。
Apacheよりも処理能力が高い。
puma(プーマ)
※1.Rackという機能を提供するためのアプリケーションサーバ。
webサーバの1つでもある。
※1.RackとはWeb サーバと Rubyやフレームワークをつなぐ最小のインタフェースを提供するもの。
Docker導入手順
① Docker for Macを公式サイトからインストール、そして起動
公式サイトで会員登録を済ませた後、Docker for Macをダウンロードしインストール。
インストールが終わったら、Dockerを起動しておく。
(MACの画面上部にDockerのマークが出れば起動できてる証拠)②作成済みのアプリケーションフォルダの直下に「Dockerfile」、「docker-compose.yml」ファイルを新しく作成する。
フォルダ構成
- 既存のRailsアプリフォルダ
- app
- bin
- config
- db
- ・・・
- Dockerfile
- docker-compose.yml
③Dockerfileに記述する(アプリケーションフォルダ直下)
DockerfileFROM ruby:2.5.1 RUN apt-get update && \ apt-get install -y mysql-client nodejs vim --no-install-recommends && \ rm -rf /var/lib/apt/lists/* RUN mkdir /myproject WORKDIR /myproject ADD Gemfile /myproject/Gemfile ADD Gemfile.lock /myproject/Gemfile.lock RUN gem install bundler RUN bundle install ADD . /myproject RUN mkdir -p tmp/sockets④docker-compose.ymlに記述する(アプリケーションフォルダ直下)
docker-compose.ymlversion: '2' services: db: image: mysql:5.6 environment: - ./environments/db.env volumes: - mysql-data:/var/lib/mysql ports: - "4306:3306" app: build: . command: bundle exec puma -C config/puma.rb volumes: - .:/myproject - public-data:/myproject/public - tmp-data:/myproject/tmp - log-data:/myproject/log web: build: context: containers/nginx volumes: - public-data:/myproject/public - tmp-data:/myproject/tmp ports: - 80:80 volumes: mysql-data: public-data: tmp-data: log-data:⑤アプリケーションフォルダ直下に「environments」フォルダを作成、さらにenvironmentsフォルダ直下に「db.env」ファイルを作成する。
- 既存のRailsアプリフォルダ
- app
- bin
- config
- db
- environments
- db.env
- ・・・
- Dockerfile
- docker-compose.yml
⑥db.envを編集
environments/db.envMYSQL_ROOT_PASSWORD=password MYSQL_USER=user MYSQL_PASSWORD=password⑦database.ymlを編集
config/database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: <%= ENV.fetch('MYSQL_USER') { 'root' } %> password: <%= ENV.fetch('MYSQL_PASSWORD') { 'root' } %> host: db⑧アプリケーションフォルダ直下に「containers」フォルダを作成、さらにcontainersフォルダ直下に「nginx」フォルダを作成する。
フォルダ構成
- 既存のRailsアプリフォルダ
- app
- bin
- config
- containers
- nginx
- db
- environments
- db.env
- ・・・
- Dockerfile
- docker-compose.yml
⑨作成したnginxフォルダ直下に「Dockerfile」、「nginx.conf」ファイルを作成する。
- 既存のRailsアプリフォルダ
- app
- bin
- config
- containers
- nginx
- Dockerfile
- nginx.conf
- db
- environments
- db.env
- ・・・
- Dockerfile
- docker-compose.yml
⑩Dockerfileに記述する(containers/nginxフォルダ直下)
containers/nginx/DockerfileFROM nginx:1.15.8 RUN rm -f /etc/nginx/conf.d/* ADD nginx.conf /etc/nginx/conf.d/myproject.conf CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf⑪nginx.confに記述する(containers/nginxフォルダ直下)
containers/nginx/nginx.confupstream myproject { server unix:///myproject/tmp/sockets/puma.sock; } server { listen 80; server_name 13.112.60.229; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; root /myproject/public; client_max_body_size 100m; error_page 404 /404.html; error_page 505 502 503 504 /500.html; try_files $uri/index.html $uri @myproject; keepalive_timeout 5; location @myproject { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://myproject; } }⑫puma.rbを編集
puma.rbapp_root = File.expand_path("../..", __FILE__) bind "unix://#{app_root}/tmp/sockets/puma.sock" stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true⑬ターミナルでコマンドを実行
ファイルの準備が整ったら、最後にターミナル上でコマンドを実行。
(railsアプリケーションフォルダ内で実行する)イメージを構築する
ターミナル$ docker-compose buildrailsのコンテナを作成し、データベースの作成処理を行う
ターミナル$ docker-compose run --rm app rake db:create db:migrate全てのコンテナを構築・起動する
ターミナル$ docker-compose up上記の流れが終わったあとlocalhostにアクセスすると、しっかり確認することができました。
ちなみに今回書きまとめたものは、DBもDockerで管理することになりますが、DBはローカルのものを参照したいという場合、以下の記事が参考になるかと思います。
既存のRailsアプリをDocker化し、ローカルのDBに接続する方法(おまけ)
Dockerfileに記述できるコマンド一覧
コマンド 意味 FROM ベースとなるイメージ RUN docker build 時に実行するコマンド CMD docker run 時に実行するコマンド ENTRYPOINT docker run 時に実行するコマンド MAINTAINER 作者情報 LABEL ラベル情報(メタデータ) EXPOSE 公開ポート番号 ENV 環境変数 ARG 一時変数 COPY ホストからコンテナへのファイルコピー ADD ファイル/ディレクトリの追加 VOLUME ボリュームのマウント USER 実行ユーザ SHELL シェル指定 WORKDIR ワークディレクトリ ONBUILD ビルド時に実行するコマンド STOPSIGNAL コンテナ終了時に送信されるシグナル HEALTHCHECK ヘルスチェック ターミナル上で実行できるdocker-composeコマンド一覧
コマンド 意味 build サービスの構築または再構築 config compose ファイルの確認と表示 create サービスの作成 down コンテナ・ネットワーク・イメージ・ボリュームの停止と削除 events コンテナからリアルタイムにイベントを受信 help コマンド上でヘルプを表示 kill コンテナを kill (強制停止) logs コンテナの出力を表示 pause サービスを一時停止 port ポートに割り当てる公開用ポートを表示 ps コンテナ一覧 pull サービス用イメージの取得 restart サービスの再起動 rm 停止中のコンテナを削除 run 1度だけコマンドを実行 scale サービス用コンテナの数を指定ド start サービスの開始 stop サービスの停止 up コンテナの作成と開始 version Docker Compose のバージョン情報を表示
- 投稿日:2020-01-10T13:49:18+09:00
既存のRailsアプリをDocker上で環境構築する方法+sequel proによるDBコンテナ可視化
はじめに
新規アプリをDocker環境で開発するやり方はたくさんあるけど、既存アプリをDocker環境で構築するやり方は全然見当たらず、わりと苦労しました。
振り返ってみると新規アプリでの構築の仕方とあまり変わらないはずなのですが、色々エラー出て苦労したのでまとめておきます。個々のコマンドの意味もできるだけ記載しました。
単なる環境構築だけでなく、DBコンテナのsequel proによる可視化やAPPコンテナでのbinding.pryの仕方、bundle install後にbuildし直さなくてもよい設定にする方法などもまとめました。同じく既存のRailsアプリをDocker上で構築したい人の参考になれば幸いです。
内容について間違っていたら教えていただけると嬉しいです。
開発環境
- Ruby: 2.5.1
- Rails: 5.2.4
- MySQL: 5.6
- MacOS
前提
- Docker for Macはインストール済み
- Dockerについての基礎知識
- 今回は開発環境のみ
対象読者
作成した既存のアプリをDocker上で構築したい人
目次
- コンテナ起動までの大まかな流れ
- 実際の作業
- 番外編:sequel proによるDBコンテナの可視化
- 開発する上でのDockerコマンド
- おまけ
- railsコンテナ上でbinding.pryをする方法
- railsコンテナ上でbundle installした時に、変更内容をコンテナ上に反映させる方法
コンテナ起動までの大まかな流れ
DockerfileにてRubyのベースイメージをもとにイメージを作成する
↓
作成したイメージをもとにdocker-compose.ymlでappコンテナを作成すると同時に、DBのコンテナのイメージを作成し、これらのコンテナを連携させる
↓
database.ymlを修正してappコンテナからdbコンテナへ接続できるように設定する実際の作業
- Dockerfileとdocker-compose.ymlの作成
- Dockerfileの記載
- docker-compose.ymlの記載
- database.ymlの変更
1. Dockerfileとdocker-compose.ymlの作成
まず、開発しているアプリで、Dockerfileとdocker-compose.ymlを以下のように作成します。
アプリ名 |- app |- bin |- config #略 |- vendor - .gitignore - config.rb - Dockerfile #追加 - docker-compose.yml #追加 - Gemfile - Gemfile.lock #略2. Dockerfileの記載
続いてDockerfileの中身を書いていきます。
myprojectのところはコンテナ起動の際に作成するディレクトリ名なので、何でも大丈夫です
ただし、それ以降の記述でも随時書き換えてくださいDockerfileFROM ruby:2.5.1 RUN apt-get update && \ apt-get install -y mysql-client nodejs vim --no-install-recommends && \ rm -rf /var/lib/apt/lists/* RUN mkdir /myproject WORKDIR /myproject ADD Gemfile /myproject/Gemfile ADD Gemfile.lock /myproject/Gemfile.lock RUN gem install bundler RUN bundle install ADD . /myproject詳細な説明は省きますが、ざっと説明すると
- ruby2.5.1をベースイメージとする
- コンテナ内で必要なコマンドをインストール
- myprojectというディレクトリを作成して基点にする
- Gemfileをコンテナ上にコピーした後、bundle install
- ローカルのディレクトリ、ファイルをコンテナ上にコピー
という感じかと思います。
3. docker-compose.ymlの記載
Rubyのコンテナは作成できるようになりました。
続いてこれをもとにアプリケーションのコンテナとデータベースのコンテナを作成し、それらのコンテナをリンクさせるための作業をしていきます。
docker-compose.ymlを以下のように記載します。
*mysqlは8.0以上だと認証方法が異なるようなので注意
https://qiita.com/yensaki/items/9e453b7320ca2d0461c7docker-compose.ymlversion: '2' services: db: image: mysql:5.6 volumes: - mysql-data:/var/lib/mysql #データの永続化のために必要 ports: - "4306:3306" #両方3306でもok。詳細は下の「番外編:DBをsequel proで可視化したい」へ app: tty: true #コンテナ上でbinding.pryするために必要 stdin_open: true #コンテナ上でbinding.pryするために必要 build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/myproject #ローカルのディレクトリをコンテナ上にマウント - bundle:/usr/local/bundle #bundle installした後buildし直さなくてよくなる links: - db volumes: mysql-data: bundle: #bundle installした後buildし直さなくてよくなる要点は以下
- versionは2でも3でもいいと思いますが、使えるコマンドが違ってくるみたいです。
- servicesのところにdbとappがありますが、これらがそれぞれコンテナになります。
- appのコンテナのlinksにdbがあり、これによってappコンテナとdbコンテナが連携できるようになります
- 一番下のvolumesには永続化させたいデータを記載
- appコンテナ上でvolumes: - .:/myprojectとすることで、ローカルのディレクトリをマウントしている。
- dbコンテナ上でvolumes: -mysql-data:/var/lib/mysqlとすることでデータベースで変更されたデータを永続化。この記述がないと、コンテナを壊した時に変更したデータが消えてしまいます。
- bundle installとbinding.pryのための記述は本記事、最後のおまけを参照
4. database.ymlの変更
これまでの作業でappコンテナとdbコンテナを連携させる設定をしました。
最後にappコンテナからdbコンテナに接続するために、接続設定をします。
database.ymlの中身はおそらく初期設定のままだとこんな感じの記述になってるかと思います。config/database.yml変更前default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: socket: /tmp/mysql.sockこのままだとsocket通信でDB接続をするので、せっかく作成したdbコンテナが意味なくなってしまいます。
作成したdbコンテナに接続するために以下のように変更します。config/database.yml変更後default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password:password host: db #変更(docker-compose.ymlのservice名を記載)usernameやpasswordは環境変数で設定している記事もいくつか見ますが、開発環境なら気にしなくてもいいかなと思いました。
本番環境ではちゃんと環境変数を設定します。以上で準備ができました。
あとはターミナルで該当アプリのディレクトリまで移動して、docker-compose upと入力するだけです
(Gemfile.lockの中身を削除して空にしないとエラーになるかもしれません)
localhost:3000で接続確認して終了です!今回はMySQLを使いましたが、他のDBでも可能なはずです(未検証)
*ポート番号は変わるはずなのでご注意ください番外編:DBをsequel proで可視化したい
今まで開発していた時、DBをsequel proで可視化していて便利だったのですが、docker上のDBも可視化したい!
という方に向けて以下に方法を記載しますdocker-compose.ymlで以下のように記載していました
Ruby:docker-compose.yml
db:
ports:
- "4306:3306"
これはホストが4306で接続した時にコンテナ上では3306に置き換えますという意味です。
準備はこれでokなのでsequel proで接続します。
sequel proを開いて、標準タブに切り替えます。
そこで以下の内容を入力します名前: 任意、変えなくてもok ホスト: 127.0.0.1 ユーザー名: root (database.ymlに記載のユーザー名) パスワード: password (database.ymlにパスワード) データベース: 空でok ポート: 4306(docker-compose.ymlのportsに記載した左側)ホストの127.0.0.1は自分自身を表すIPアドレス
これで見れるようになるはず!
その他開発する上で必要なコマンド
docker上でrails g controllerやrails db:migrateなどを行う時は以下のようにコンテナを通して入力します
appの部分はdocker-compose.ymlで作成したコンテナ名のappのことですdocker-compose run --rm app 入力したいコマンド(例: rails db:migrate)その他必要なコマンドは以下の記事参照
https://qiita.com/gold-kou/items/44860fbda1a34a001fc1
全てのコンテナやイメージを削除する場合はこちら#全てのコンテナ停止 docker stop $(docker ps -q) #全てのコンテナ削除 docker rm $(docker ps -q -a) #全てのイメージ削除 docker rmi $(docker images -q)おまけ
bundle installしたい時
開発していく中で、gemを追加してbundle installしたい場面が出てくると思います
そのままやってもできるんですが、追加したgem内容がコンテナ内に反映されないため、イメージをbuildし直さなくてはなりません。
いくつか解決方法はあるみたいですが、今回はvolumeでマウントするという方法で解決しました。docker-compose.ymlapp: volumes: - bundle:/usr/local/bundle #中略 volumes: bundle:参考記事
https://qiita.com/neko-neko/items/abe912eba9c113fd527ebindin.pryしたい時
binding.pryをするためには以下の記述を追加します
docker-compose.ymlapp: tty: true stdin_open: trueおわりに
dockerについて全くわからないところから環境構築するのはかなり大変でした
自分なりにまとめられて良かった
同じような状況の人の参考になれば幸いです間違ってる場所があれば指摘していただけると幸いです
本番環境でDockerを使うのも苦労したので、そのうち開発環境との違いなどもまとめようかなと思います
参考記事
Dockerについての概要と色々なTIPSを知りたい場合は下記リンクがおすすめ
https://qiita.com/gold-kou/items/44860fbda1a34a001fc1実際の作業で参考にした記事
https://qiita.com/azul915/items/5b7063cbc80192343fc0
https://qiita.com/Nishi53454367/items/aee4cf0c346bc115be99
- 投稿日:2020-01-10T13:49:18+09:00
既存のRailsアプリをDockerコンテナで動かす方法+sequel proによるDBコンテナ可視化
はじめに
新規アプリをDocker環境で開発するやり方はたくさんあるけど、既存アプリをDocker環境で構築するやり方は全然見当たらず、わりと苦労しました。
振り返ってみると新規アプリでの構築の仕方とあまり変わらないはずなのですが、色々エラー出て苦労したのでまとめておきます。個々のコマンドの意味もできるだけ記載しました。
単なる環境構築だけでなく、DBコンテナのsequel proによる可視化やAPPコンテナでのbinding.pryの仕方、bundle install後にbuildし直さなくてもよい設定にする方法などもまとめました。同じく既存のRailsアプリをDocker上で構築したい人の参考になれば幸いです。
内容について間違っていたら教えていただけると嬉しいです。
開発環境
- Ruby: 2.5.1
- Rails: 5.2.4
- MySQL: 5.6
- MacOS
前提
- Docker for Macはインストール済み
- Dockerについての基礎知識
- 今回は開発環境のみ
対象読者
作成した既存のアプリをDocker上で構築したい人
目次
- コンテナ起動までの大まかな流れ
- 実際の作業
- 番外編:sequel proによるDBコンテナの可視化
- 開発する上でのDockerコマンド
- おまけ
- railsコンテナ上でbinding.pryをする方法
- railsコンテナ上でbundle installした時に、変更内容をコンテナ上に反映させる方法
コンテナ起動までの大まかな流れ
DockerfileにてRubyのベースイメージをもとにイメージを作成する
↓
作成したイメージをもとにdocker-compose.ymlでappコンテナを作成すると同時に、DBのコンテナのイメージを作成し、これらのコンテナを連携させる
↓
database.ymlを修正してappコンテナからdbコンテナへ接続できるように設定する実際の作業
- Dockerfileとdocker-compose.ymlの作成
- Dockerfileの記載
- docker-compose.ymlの記載
- database.ymlの変更
1. Dockerfileとdocker-compose.ymlの作成
まず、開発しているアプリで、Dockerfileとdocker-compose.ymlを以下のように作成します。
アプリ名 |- app |- bin |- config #略 |- vendor - .gitignore - config.rb - Dockerfile #追加 - docker-compose.yml #追加 - Gemfile - Gemfile.lock #略2. Dockerfileの記載
続いてDockerfileの中身を書いていきます。
myprojectのところはコンテナ起動の際に作成するディレクトリ名なので、何でも大丈夫です
ただし、それ以降の記述でも随時書き換えてくださいDockerfileFROM ruby:2.5.1 RUN apt-get update && \ apt-get install -y mysql-client nodejs vim --no-install-recommends && \ rm -rf /var/lib/apt/lists/* RUN mkdir /myproject WORKDIR /myproject ADD Gemfile /myproject/Gemfile ADD Gemfile.lock /myproject/Gemfile.lock RUN gem install bundler RUN bundle install ADD . /myproject詳細な説明は省きますが、ざっと説明すると
- ruby2.5.1をベースイメージとする
- コンテナ内で必要なコマンドをインストール
- myprojectというディレクトリを作成して基点にする
- Gemfileをコンテナ上にコピーした後、bundle install
- ローカルのディレクトリ、ファイルをコンテナ上にコピー
という感じかと思います。
3. docker-compose.ymlの記載
Rubyのコンテナは作成できるようになりました。
続いてこれをもとにアプリケーションのコンテナとデータベースのコンテナを作成し、それらのコンテナをリンクさせるための作業をしていきます。
docker-compose.ymlを以下のように記載します。
*mysqlは8.0以上だと認証方法が異なるようなので注意
https://qiita.com/yensaki/items/9e453b7320ca2d0461c7docker-compose.ymlversion: '2' services: db: image: mysql:5.6 volumes: - mysql-data:/var/lib/mysql #データの永続化のために必要 ports: - "4306:3306" #両方3306でもok。詳細は下の「番外編:DBをsequel proで可視化したい」へ app: tty: true #コンテナ上でbinding.pryするために必要 stdin_open: true #コンテナ上でbinding.pryするために必要 build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/myproject #ローカルのディレクトリをコンテナ上にマウント - bundle:/usr/local/bundle #bundle installした後buildし直さなくてよくなる links: - db volumes: mysql-data: bundle: #bundle installした後buildし直さなくてよくなる要点は以下
- versionは2でも3でもいいと思いますが、使えるコマンドが違ってくるみたいです。
- servicesのところにdbとappがありますが、これらがそれぞれコンテナになります。
- appのコンテナのlinksにdbがあり、これによってappコンテナとdbコンテナが連携できるようになります
- 一番下のvolumesには永続化させたいデータを記載
- appコンテナ上でvolumes: - .:/myprojectとすることで、ローカルのディレクトリをマウントしている。
- dbコンテナ上でvolumes: -mysql-data:/var/lib/mysqlとすることでデータベースで変更されたデータを永続化。この記述がないと、コンテナを壊した時に変更したデータが消えてしまいます。
- bundle installとbinding.pryのための記述は本記事、最後のおまけを参照
4. database.ymlの変更
これまでの作業でappコンテナとdbコンテナを連携させる設定をしました。
最後にappコンテナからdbコンテナに接続するために、接続設定をします。
database.ymlの中身はおそらく初期設定のままだとこんな感じの記述になってるかと思います。config/database.yml変更前default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: socket: /tmp/mysql.sockこのままだとsocket通信でDB接続をするので、せっかく作成したdbコンテナが意味なくなってしまいます。
作成したdbコンテナに接続するために以下のように変更します。config/database.yml変更後default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password:password host: db #変更(docker-compose.ymlのservice名を記載)usernameやpasswordは環境変数で設定している記事もいくつか見ますが、開発環境なら気にしなくてもいいかなと思いました。
本番環境ではちゃんと環境変数を設定します。以上で準備ができました。
あとはターミナルで該当アプリのディレクトリまで移動して、docker-compose upと入力するだけです
(Gemfile.lockの中身を削除して空にしないとエラーになるかもしれません)
localhost:3000で接続確認して終了です!今回はMySQLを使いましたが、他のDBでも可能なはずです(未検証)
*ポート番号は変わるはずなのでご注意ください番外編:DBをsequel proで可視化したい
今まで開発していた時、DBをsequel proで可視化していて便利だったのですが、docker上のDBも可視化したい!
という方に向けて以下に方法を記載しますdocker-compose.ymlで以下のように記載していました
Ruby:docker-compose.yml
db:
ports:
- "4306:3306"
これはホストが4306で接続した時にコンテナ上では3306に置き換えますという意味です。
準備はこれでokなのでsequel proで接続します。
sequel proを開いて、標準タブに切り替えます。
そこで以下の内容を入力します名前: 任意、変えなくてもok ホスト: 127.0.0.1 ユーザー名: root (database.ymlに記載のユーザー名) パスワード: password (database.ymlにパスワード) データベース: 空でok ポート: 4306(docker-compose.ymlのportsに記載した左側)ホストの127.0.0.1は自分自身を表すIPアドレス
これで見れるようになるはず!
その他開発する上で必要なコマンド
docker上でrails g controllerやrails db:migrateなどを行う時は以下のようにコンテナを通して入力します
appの部分はdocker-compose.ymlで作成したコンテナ名のappのことですdocker-compose run --rm app 入力したいコマンド(例: rails db:migrate)その他必要なコマンドは以下の記事参照
https://qiita.com/gold-kou/items/44860fbda1a34a001fc1
全てのコンテナやイメージを削除する場合はこちら#全てのコンテナ停止 docker stop $(docker ps -q) #全てのコンテナ削除 docker rm $(docker ps -q -a) #全てのイメージ削除 docker rmi $(docker images -q)おまけ
bundle installしたい時
開発していく中で、gemを追加してbundle installしたい場面が出てくると思います
そのままやってもできるんですが、追加したgem内容がコンテナ内に反映されないため、イメージをbuildし直さなくてはなりません。
いくつか解決方法はあるみたいですが、今回はvolumeでマウントするという方法で解決しました。docker-compose.ymlapp: volumes: - bundle:/usr/local/bundle #中略 volumes: bundle:参考記事
https://qiita.com/neko-neko/items/abe912eba9c113fd527ebindin.pryしたい時
binding.pryをするためには以下の記述を追加します
docker-compose.ymlapp: tty: true stdin_open: trueおわりに
dockerについて全くわからないところから環境構築するのはかなり大変でした
自分なりにまとめられて良かった
同じような状況の人の参考になれば幸いです間違ってる場所があれば指摘していただけると幸いです
本番環境でDockerを使うのも苦労したので、そのうち開発環境との違いなどもまとめようかなと思います
参考記事
Dockerについての概要と色々なTIPSを知りたい場合は下記リンクがおすすめ
https://qiita.com/gold-kou/items/44860fbda1a34a001fc1実際の作業で参考にした記事
https://qiita.com/azul915/items/5b7063cbc80192343fc0
https://qiita.com/Nishi53454367/items/aee4cf0c346bc115be99
- 投稿日:2020-01-10T13:16:31+09:00
Dockerで始めるLaravel講座 - Docker編
はじめに
気づけばオリンピックイヤーである2020年がしれっと始まりましたが皆様いかがお過ごしでしょうか。
さて、今日は「Dockerで始めるLaravel講座」のDocker編です。
今日はサクサクっとどうやってDockerを使うのかを学んでいきましょう。
アジェンダ
今日はこんな順番でお話していきます。
- Dockerをはじめてみよう
- docker-composeでより本番に近づけてみよう
Dockerをはじめてみよう
Kitematicを入れてみよう
Dockerがまずピンときてないときは、まずはピンときてしまうことです。
そのためにDockerには Kitematic(カイトマティック) という素晴らしいGUIダッシュボードツールがあります。最新版はこちらからダウンロードできます。
https://github.com/docker/kitematic/releases
なんとかかんとかインストールして開いてみるとこんな画面になると思います。
せっかくなので、ここからApache(httpd)でも立ち上げてみましょう。
Search for Docker images ~と書かれている検索ボックスにhttpdと入れてみましょう。
するとこんな感じになると思います。
では、ここで左上の
official httpdと書かれているボックスの右下にあるCREATEをクリックしてみましょう。
すると何やらダウンロードを始めて、謎のコンソール画面が出てくると思います。
そう、何を隠そう、これで実はApacheのDockerコンテナが立ち上がっている状態なのです。
試しに右上のHomeSettingsと書かれているタブをSettingsに切り替えてから中のタブをHostname/Portsに切り替えてConfigure Portsのlocalhost:xxxxと書かれているところをクリックしてみましょう。
するとブラウザに
It works!と表示されているはずです。
おめでとう! Apacheが立ち上がっていますね!
せっかくApache立ち上がったのでApacheの中に入ってみましょうか。
Kitematicに戻ってみるとEXECって書いてあるところがあるのでポチーしてみましょう。
するとなにやら黒い画面が現れてきます。
そう、これでDockerで立ち上げた仮想環境の中に入っているのです。せっかくなので、入ってる気分を体験してみましょう。
こちらのコマンドを順に打ち込んでみてください。
$ apt update $ apt install -y vim $ cd htdocs $ vi index.html
すると、さっき表示していた
It Works!の文字を表示していたHTMLファイルが開けます。
こいつをちょちょいと弄ってみてさっきのブラウザをリロードしてみましょう。表示、変わりましたか?
ではもう用済みなので、このコンテナは消してやりましょう。
Kitematicのここをクリックしてみてください。
ローカルのファイルをDockerコンテナに反映させよう
コンテナでただ遊ぶ分にはさっきの方法でもいいのですが、ちゃんと開発で使おう!と思うといちいちコンテナの中に入ってvimでファイルを開いて編集……というやり方でやってたら全然効率がよくありません。
やっぱ「Dockerやめて素直にXAMPP使うぜ」になってしまいます。
じゃあどうしたらいいのか。
VirtualBoxとかVagrantで仮想環境を使った開発をしたことある人ならもうピンときていると思いますが「共有フォルダ」機能を使えばいいのです。
ちゃんとDockerにもありますよ!
ただこれ、Kitematicからは設定できないので、コマンドラインから実行する必要があります。
Kitematicの画面の左下に
DOCKER CLIと書かれたボタンが有るの分かりますか? そこをポチーしてみましょう。
実行する環境によって出てくるものが若干違うと思いますが、これまた黒い画面が現れてきます。
Windowsならコマンドプロンプトが、Macならターミナルの画面が出てきてると思います。
多分なんとなくわかったと思いますが、実はKitematicなど使わなくてもDockerは使えます。あ、知ってましたかね?
ではデスクトップに
docker-testというフォルダを作って中にindex.htmlを作ってみてください。
index.htmlの内容は何でもいいです。
HTMLの書き方がわからなければ下をコピペしてください。<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Test</title> </head> <body> やったねたえちゃん、家族が増えたよ </body> </html>
できたらターミナルの画面でなんとかかんとかデスクトップまでたどり着いてください。
そこで下記コマンドを入力してみてください。docker run -v $(pwd)/docker-test:/usr/local/apache2/htdocs -d -p 8080:80 httpd今度はブラウザで
http://localhost:8080を開いてみてください。
さっき作ったやつになりましたよね?
docker-composeでより本番に近づけてみよう
そもそもなんでDockerを使うのか
割と肝心の話をしてなかったような気がしますね。
当たり前なのですが、Web開発におけるローカル開発環境の手段はDockerだけではありません。
大まかには以下の3通りのどれかになるかと思います。
- ローカルのOSにApache/PHP/MySQLなどのミドルウェアを直接入れて開発する
- VirtualBoxなどのVM型仮想環境を使う
- Dockerなどのコンテナ型仮想環境を使う
それぞれにメリット・デメリットはあるのですが、大体のケースに置いてDockerはおすすめです。
かんたんにメリット・デメリットまとめるとこんな感じですかね。
方法 メリット デメリット 直ミドルウェア かんたん(何なら最初から入ってることも) 環境が汚れてしまうので複数案件まわせない。たくさん建てるのは無理 VM どこでも安定して動く。 おもい。たくさん立てるのが大変(できないことはない) コンテナ サクサク立てられる。一度にたくさん立てられる 一部できないことがある
つまり、たくさん立てないといけないときはほぼDocker一択という選択になります。
僕が初めてDockerを仕事で作ったときはこんな構成でした。
APIサーバーと管理画面サーバーが同じDBにアクセスする構成ですね。
こんな感じの構成をちゃちゃっと作るのにはDockerの一機能である
docker-composeというのが威力を発揮します。
いや、まあ、kubernetesとかもあるっちゃあるのですが、それはまたどこかでやりましょう。
ではさっき作ったtest-dockerフォルダの中にこんな内容の
docker-compose.ymlを作ってみてください。version: '2.1' services: mysql: image: mysql:5.6 volumes: - './mysql/var/log/mysql:/var/lib/mysql' ports: - '4306:3306' environment: MYSQL_ROOT_PASSWORD: rootPass11111111 MYSQL_DATABASE: laratest MYSQL_USER: larauser MYSQL_PASSWORD: larapass api: image: httpd links: - mysql ports: - '8081:80' volumes: - './api:/usr/local/apache2/htdocs' admin: image: httpd links: - mysql ports: - '8082:80' volumes: - './admin:/usr/local/apache2/htdocs'
できたらこんどは、apiとadminディレクトリを作ってそこにindex.htmlをおいてみましょう。
内容はちょこっとだけ変えたほうが良いですね。
では、docker-composeを起動してみましょう。
こちらのコマンドを打ち込んでみてください。
$ docker-compose up -dすると楽しいことが起きていると思います。
Kitematicを見てみると一気に3つコンテナが立ち上がってるのがわかると思います。
こうすることによってマルチコンテナ構成を簡単に作れるのです。
次回はこのDocker環境を使ってLaravelのアプリケーションを作っていきたいと思います。
おつかれさまでした!
- 投稿日:2020-01-10T12:56:25+09:00
コマンドラインからDocker Hubで公開されているイメージの「タグ」を検索するためのツールを作りました
はじめに
Docker で開発をすすめる機会が増えてくると、だんだん「タグ」を調べることが多くなってきます。
Docker における タグ とは、たとえば MySQL公式イメージを利用する際に
mysql:8.0.18のように指定する コロン の後ろの部分になります。同じDockerイメージでも、 「タグ」 の違いにより機能が異なります。
PHPでもFPM対応もの、Apache対応のもの、 コマンドラインだけで動作するものなどが用意されており、それぞれ以下の用意なっています。
php:fpmphp:apachephp:cli「タグ」を覚えたり調べたりは面倒
「タグ」を調べるにはどうしたらよいでしょう?
Docker Hub のサイトで該当イメージを探し、タグの値を探せばよいです。
しかし、せっかくコーディングがフロー状態に入ってきたり、あるいは CUIの世界から出たくない! という方々も多いと思います。
コマンドラインから「タグ」を検索するツールを作った
そこでDockerの学習も兼ねて「タグ」を検索するツールを作りました。
ツール自体も
Dockerで動きます。
ですので、dockerコマンドをコマンドラインから利用できるようにしてください。使い方
機能自体が少ないので、 Github上のREADME を見ていただければ1分でわかるかと思います。
-hオプションを指定して実行した結果だけ、貼り付けておきます。docker-tags [-p PAGE] [-a] [-h] -p : Output the specified number of pages.( DEFAULT : 5 ) -a : Output all pages. -h : Output Help.デフォルトでは5ページ(50タグ)分が出力されますが、
-fオプションあるいは-pオプションで件数を変更できます。実行結果は以下のようになります。
TAG SIZE UPDATED ----- ----- ----- latest 134026357 2019-12-29T01:03:04.158114Z 8.0.18 134026357 2019-12-29T01:03:02.024679Z 8.0 134026357 2019-12-29T01:03:00.45482Z 8 134026357 2019-12-29T01:02:58.07512Z 5.7.28 150505380 2019-12-29T01:02:46.654066Z 5.7 150505380 2019-12-29T01:02:44.854124Z 5.6.46 102683838 2019-12-29T01:02:42.938573Z 5.6 102683838 2019-12-29T01:02:38.761685Z 5 150505380 2019-12-29T01:02:22.579441Z 8.0.17 129970553 2019-09-12T06:03:06.99785Z 5.7.27 124130524 2019-09-12T06:02:47.200186Z 5.6.45 82841471 2019-09-12T06:02:42.262232Z 8.0.16 129388433 2019-07-17T22:47:34.737755Z 5.7.26 124147701 2019-07-17T22:47:18.044464Z 5.6.44 82831221 2019-07-17T22:47:12.767655Z 5.5.62 66072546 2019-05-10T23:43:35.219656Z ...ひとこと
フィードバッグお待ちしております。
- 投稿日:2020-01-10T07:05:14+09:00
GCE上でContainer-Optimized OSを使ってコンテナバッチ処理する方法
Container-Optimized OSを使ってGCE上でコンテナバッチ処理する方法のメモ。
コンテナバッチ処理後はコンテナ内でVMを削除するため、VM稼働分のコストで済みます。
コードはGithubにあげています。
https://github.com/yolo-kiyoshi/gce_docker_cliフォルダ構成root/ ├ .env ├ .param ├ Dockerfile ├ Pipfile ├ Pipfile.lock ├ *********.json(credentialファイル) ├ scripts/ │ └ build_and_push.sh │ └ deploy_container.sh └ src/ └ delete_vm.py └ main.py準備
VM起動パラメータ
VM起動パラメータを
.paramに記載します。SERVICE_ACCOUNT=********* PROJECT_ID=********* MACHINE_TYPE=n1-standard-1Credentialファイル
Dockerfileと同一ディレクトリにCredentialファイル(json)を配置します。コンテナ環境変数
コンテナ環境変数を
.envに記載します。
Credentialファイル(json)pathを必ず GOOGLE_APPLICATION_CREDENTIALS に記載します。GOOGLE_APPLICATION_CREDENTIALS=/app/************.json概要
- GCRにDockerイメージをプッシュ
- GCRのイメージからGCE上のVMにコンテナをデプロイ。コンテナ処理終了後、VMを削除
GCRにDockerイメージをプッシュ
Dockerイメージをビルドし、GCRにイメージをプッシュするスクリプトです。
scripts/build_and_push.sh#!/usr/bin/env bash set -eu image=${1:-} tag=${2:-latest} # read param . .param fullname="gcr.io/${PROJECT_ID}/${image}:${tag}" # read setting file docker build -t ${image}:${tag} . docker tag ${image}:${tag} ${fullname} docker push ${fullname} echo "image successfully pushed to: ${fullname}"
Dockerfileと同一ディレクトリで以下を実行すると、GCRにDockerイメージをプッシュできます。Dockerビルド&GCRへのプッシュsh scripts/build_and_push.sh <イメージ名> <タグ>GCRのイメージからGCE上のVMにコンテナをデプロイ。コンテナ処理終了後、VMを削除
GCRのイメージからGCE上のVMにコンテナをデプロイするスクリプトです。
deploy_container.sh#!/usr/bin/env bash set -eu service=${1:-} image=${2:-} tag=${3:-latest} # read param . .param fullname="gcr.io/${PROJECT_ID}/${image}:${tag}" gcloud compute instances create-with-container ${service} \ --container-image=${fullname} \ --container-env-file=.env \ --container-restart-policy=never \ --machine-type=${MACHINE_TYPE} \ --service-account=${SERVICE_ACCOUNT}VMを削除するモジュールです。
src/delete_vm.pyfrom googleapiclient import discovery from oauth2client.client import GoogleCredentials import requests def delete_vm(): # credentialオブジェクト取得 credentials = GoogleCredentials.get_application_default() service = discovery.build('compute', 'v1', credentials=credentials) # メタデータサーバからプロジェクトID, インスタンンス名, ゾーンを取得する project_id = requests.get( "http://metadata.google.internal/computeMetadata/v1/project/project-id", headers={"Metadata-Flavor": "Google"} ).text name = requests.get( "http://metadata.google.internal/computeMetadata/v1/instance/name", headers={"Metadata-Flavor": "Google"} ).text zone_long = requests.get( "http://metadata.google.internal/computeMetadata/v1/instance/zone", headers={"Metadata-Flavor": "Google"} ).text zone = zone_long.split("/")[-1] print(f'[delete target] project_id:{project_id},name:{name},zone:{zone}') # VMインスタンス削除 request = service.instances().delete( project=project_id, zone=zone, instance=name ) request.execute()
mainの最後(finally)でVM削除処理を行います。src/main.pyfrom delete_vm import delete_vm try: print('process start.') ###################### # process ###################### print('process end.') finally: delete_vm()
Dockerfileと同一ディレクトリで以下を実行すると、GCRのDockerイメージをもとにVMにコンテナをデプロイします。
コンテナ内での処理終了後はVMを削除します。sh scripts/deploy_container.sh <サービス名> <イメージ名> <タグ>参考
How to make GCE instance stop when its deployed container finishes?
Google公式ドキュメント












