- 投稿日:2020-01-19T23:59:37+09:00
LaradockでLaravelの環境構築するもMysqlが立ち上がらない!
開発環境
- macOS Mojave 10.14.4
- Laravel6.(php7.3以上)
- Mysql8.
環境構築:参考記事
初心者でもLaradockでLaravelの環境構築をエラーなしで行おう!(Mac ver)
初心者なりに環境構築で詰まったところを共有します。
記事を参考に進めていく途中
docker-compose up -d nginx mysql phpmyadmin
mysqlが立ち上がらない
Docker再起動しても立ち上がらない!
困った!エラー内容
Recreating laradock_mysql_1 ... error ERROR: for mysql Cannot start service mysql: driver failed programming external connectivity on endpoint laradock_mysql_1(aa02fd7a36f486c3c62720a98798b7625cd855e49b5c4ef25b26a425e1299e0c): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use3306が既に使われているってことか?
ググる...
Laradock公式にこんな記述が
docker-compose.ymlの中のports欄を消せばよいとのお告げ
docker-compose.yml### MySQL ################################################ mysql: build: context: ./mysql args: - MYSQL_VERSION=${MYSQL_VERSION} environment: - MYSQL_DATABASE=${MYSQL_DATABASE} - MYSQL_USER=${MYSQL_USER} - MYSQL_PASSWORD=${MYSQL_PASSWORD} - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - TZ=${WORKSPACE_TIMEZONE} volumes: - ${DATA_PATH_HOST}/mysql:/var/lib/mysql - ${MYSQL_ENTRYPOINT_INITDB}:/docker-entrypoint-initdb.d ports: - "${MYSQL_PORT}:3306" networks: - backendports: - "${MYSQL_PORT}:3306"
これを削除してみる...再度
docker-compose up -d nginx mysql phpmyadmin
できた!ありがとうLaradock公式!!
- 投稿日:2020-01-19T23:59:37+09:00
悲劇!LaradockでLaravelの環境構築するもMysqlが立ち上がらない!
開発環境
- macOS Mojave 10.14.4
- Laravel6.(php7.3以上)
- Mysql8.
環境構築:参考記事
初心者でもLaradockでLaravelの環境構築をエラーなしで行おう!(Mac ver)
初心者なりに環境構築で詰まったところを共有します。
記事を参考に進めていく途中
docker-compose up -d nginx mysql phpmyadmin
mysqlが立ち上がらない
Docker再起動しても立ち上がらない!
困った!エラー内容
Recreating laradock_mysql_1 ... error ERROR: for mysql Cannot start service mysql: driver failed programming external connectivity on endpoint laradock_mysql_1(aa02fd7a36f486c3c62720a98798b7625cd855e49b5c4ef25b26a425e1299e0c): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use3306が既に使われているってことか?
ググる...
Laradock公式にこんな記述が
docker-compose.ymlの中のports欄を消せばよいとのお告げ
docker-compose.yml### MySQL ################################################ mysql: build: context: ./mysql args: - MYSQL_VERSION=${MYSQL_VERSION} environment: - MYSQL_DATABASE=${MYSQL_DATABASE} - MYSQL_USER=${MYSQL_USER} - MYSQL_PASSWORD=${MYSQL_PASSWORD} - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - TZ=${WORKSPACE_TIMEZONE} volumes: - ${DATA_PATH_HOST}/mysql:/var/lib/mysql - ${MYSQL_ENTRYPOINT_INITDB}:/docker-entrypoint-initdb.d ports: - "${MYSQL_PORT}:3306" networks: - backendports: - "${MYSQL_PORT}:3306"
これを削除してみる...再度
docker-compose up -d nginx mysql phpmyadmin
できた!ありがとうLaradock公式!!
- 投稿日:2020-01-19T23:31:36+09:00
Docker で Cron を設定しようとしたときにハマったこと
こんな感じの Dockerfile で Cron が動くかな、と思って作業を開始しました:
DockerfileFROM tomcat ADD crontab /var/spool/crontab/root ADD run.sh /bin/run.sh CMD ["sh","/bin/run.sh"]crontab* * * * * echo "test" >> /var/tmp/testrun.sh/etc/init.d/cron start tail -f /dev/nullはたして、crontab に記載した通りに動きません。シェルにログインして確認してみましょう:
# ps -aef | grep cron root 63 57 0 12:49 pts/0 00:00:00 grep cronCron デーモンが動いていません。たたき起こしてみましょう:
# cron bash: cron: command not foundそもそも cron が入っていませんので、それは動きませんね。
Cron を追加する
今回はベースイメージが debian 系なので、
apt install cron
でインストールしてみましょう:apt install cron Reading package lists... Done Building dependency tree Reading state information... Done E: Unable to locate package cron
今度はパッケージが見つからないようです。ソースリストを確認します:
/etc/apt/sources.list# deb http://snapshot.debian.org/archive/debian/20191224T000000Z stretch main deb http://deb.debian.org/debian stretch main # deb http://snapshot.debian.org/archive/debian-security/20191224T000000Z stretch/updates main deb http://security.debian.org/debian-security stretch/updates main # deb http://snapshot.debian.org/archive/debian/20191224T000000Z stretch-updates main deb http://deb.debian.org/debian stretch-updates main
main
レポジトリのみが有効化されており、公式にサポートされるソフトウェア以外はインストールできなくなっています。universe
レポジトリを有効化してあげる必要がありますね。このままソースリストを編集したいところですが、現状は vim すら入っていないので一度 Dockerfile を修正しておきましょう:
FROM tomcat ADD sources.list /etc/apt/sources.list RUN apt update RUN apt install -y cron ADD crontab /var/spool/crontab/root ADD run.sh /bin/run.sh CMD ["sh","/bin/run.sh"]sources.list# deb http://snapshot.debian.org/archive/debian/20191224T000000Z stretch main deb http://deb.debian.org/debian stretch main universe # deb http://snapshot.debian.org/archive/debian-security/20191224T000000Z stretch/updates main universe deb http://security.debian.org/debian-security stretch/updates main universe # deb http://snapshot.debian.org/archive/debian/20191224T000000Z stretch-updates main universe deb http://deb.debian.org/debian stretch-updates main universeできたイメージからインスタンスを再生製して、シェルにログインします。状態を確認してみましょう:
# ps -aef | grep cron root 46 0 0 13:23 ? 00:00:00 /usr/sbin/cron root 80 10 0 13:43 pts/0 00:00:00 grep cron # crontab -l no crontab for rootCron デーモンは稼働していますが、crontab が読み込まれていません。あれ?
Crontab を読み込ませる
たしかに Cron の設定ファイルは
/var/spool/cron/[ユーザ名]
に保存されますが、ファイルを追加しただけでは Crontab をインストールしてくれません。 そのため、Dockerfile は以下のように修正する必要があります:FROM tomcat ADD sources.list /etc/apt/sources.list RUN apt update RUN apt install -y cron ADD crontab /var/spool/crontab/root RUN crontab /var/spool/crontab/root ADD run.sh /bin/run.sh CMD ["sh","/bin/run.sh"]
crontab [ファイル名]
を利用して、配置したファイルを元に crontab をインストールしています。なんだか冗長ですが致し方ありません。最後に、インストールに成功したか確認してみましょう:# crontab -l * * * * * echo "test" >> /var/tmp/test # tail -f /var/tmp/test test test大丈夫そうですね! ちなみに、以下のように crontab をインラインで記載することで構成をシンプルにすることができます:
(crontab -l; echo " * * * * * echo 'test' >> /var/tmp/test") | crontab参考リンク
- 投稿日:2020-01-19T23:04:00+09:00
Windows10 HomeでDockerを使うときのメモ
はじめに
普段の業務での開発環境はUbuntuなのですが、わけあって私物のwin10 Homeで開発をする機会ができたので、そのときの環境構築手順のメモです。
普段業務で散々お世話になっているので、いい機会だと思い初投稿。やりたいこと
- Pythonの開発環境を作りたいが、Anacondaは結構な頻度でハマるポイントに出会うので使いたくない
- 普段使う開発環境(Ubuntu 18.04 LTS)になるべく近付けたい
ということで、Docker入れてubuntuのコンテナをpythonのバージョン毎に個別に建てるのが何も考えずに出来てきっと楽。
pythonのライブラリはrequirement.txt作って使いまわし、python自体のバージョンはDockerfileの時点で書き換えるつもり。0. 実行時の環境
作業開始時点で環境構築に影響がありそうなのは以下くらい。
- Windows10 Home
- Git for Windows(2.18.0.windows.1)
基本的にGit bash使って作業しています。
1. Dockerのインストール
Docker for WindowsはHomeだと使えないので、Docker Toolboxをインストールする。
https://github.com/docker/toolbox/releasesから最新版のインストーラをダウンロードし実行。記事作成時は19.03.1でした。
終了後、以下の3つのアイコンがデスクトップに作成されているはずなので、一番右のDocker Quickstart Terminalを実行。
ターミナルが立ち上がって初期設定が始まるので、しばらく待つ。DockerのクジラのAAが無事出れば多分無事成功2. Docker周りの準備
無事Dockerのインストールが終了したので、ubuntuのイメージを持ってくる
$ docker pull ubuntu:18.04
無事pull出来ていれば、以下のコマンドで確認できる。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 18.04 ccc6e87d482b 3 days ago 64.2MB
3. Python環境の準備
上記imageをベースにpythonの開発環境が整ったimageを作成するため、適当なディレクトリを作り、Dockerfileを用意。
よく使うDockerfileの中身はこんな感じ。RUNたくさん使うとレイヤーが増えて良くないとか見た気もするけど、自分で使うだけなので気にしない方針。
python3.8とかにしたい場合は、Dockerfileの中身のpythonの部分だけ書き換えれば多分問題ないです。FROM ubuntu:18.04 RUN apt update && apt upgrade -y RUN apt install vim python3.7 python3.7-distutils curl -y RUN ln -s /usr/bin/python3.7 /usr/bin/python RUN curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" && python get-pip.py RUN apt autoremove上記を元にimageを作成。
# imageの作成 $ docker build -t <image name> . # 作成したimageの確認(今回はu18_py37という名前で作成) $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE u18_py37 latest 86bc6cf8e1a9 7 hours ago 214MB ubuntu 18.04 ccc6e87d482b 3 days ago 64.2MB4. 実行
上記imageを使ってコンテナをたてる。
$ docker run --net host --name test -v //c/Users/<User Name>/docker:/wrk -it u18_py37 bashおわりに
とりあえず環境構築自体はこんな感じでしょうか。
ここのやり方良くない等、ご指摘あればよろしくお願いします。
作った環境で初めてwebAPI叩くコード書いたりするのですが、それはまたそのうち別記事で。
- 投稿日:2020-01-19T23:04:00+09:00
Windows10 HomeでのDockerを使ったpython環境構築手順メモ
はじめに
普段の業務での開発環境はUbuntuなのですが、わけあって私物のwin10 Homeで開発をする機会ができたので、そのときの環境構築手順のメモです。
普段業務で散々お世話になっているので、いい機会だと思い初投稿。やりたいこと
- Pythonの開発環境を作りたいが、Anacondaは結構な頻度でハマるポイントに出会うので使いたくない
- 普段使う開発環境(Ubuntu 18.04 LTS)になるべく近付けたい
ということで、Docker入れてubuntuのコンテナをpythonのバージョン毎に個別に建てるのが何も考えずに出来てきっと楽。
pythonのライブラリはrequirement.txt作って使いまわし、python自体のバージョンはDockerfileの時点で書き換えるつもり。0. 実行時の環境
作業開始時点で環境構築に影響がありそうなのは以下くらい。
- Windows10 Home
- Git for Windows(2.18.0.windows.1)
基本的にGit bash使って作業しています。
1. Dockerのインストール
Docker for WindowsはHomeだと使えないので、Docker Toolboxをインストールする。
https://github.com/docker/toolbox/releasesから最新版のインストーラをダウンロードし実行。記事作成時は19.03.1でした。
終了後、以下の3つのアイコンがデスクトップに作成されているはずなので、一番右のDocker Quickstart Terminalを実行。
ターミナルが立ち上がって初期設定が始まるので、しばらく待つ。DockerのクジラのAAが無事出れば多分無事成功2. Docker周りの準備
無事Dockerのインストールが終了したので、ubuntuのイメージを持ってくる
$ docker pull ubuntu:18.04
無事pull出来ていれば、以下のコマンドで確認できる。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 18.04 ccc6e87d482b 3 days ago 64.2MB
3. Python環境の準備
上記imageをベースにpythonの開発環境が整ったimageを作成するため、適当なディレクトリを作り、Dockerfileを用意。
よく使うDockerfileの中身はこんな感じ。RUNたくさん使うとレイヤーが増えて良くないとか見た気もするけど、自分で使うだけなので気にしない方針。
python3.8とかにしたい場合は、Dockerfileの中身のpythonの部分だけ書き換えれば多分問題ないです。FROM ubuntu:18.04 RUN apt update && apt upgrade -y RUN apt install vim python3.7 python3.7-distutils curl -y RUN ln -s /usr/bin/python3.7 /usr/bin/python RUN curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" && python get-pip.py RUN apt autoremove上記を元にimageを作成。
# imageの作成 $ docker build -t <image name> . # 作成したimageの確認(今回はu18_py37という名前で作成) $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE u18_py37 latest 86bc6cf8e1a9 7 hours ago 214MB ubuntu 18.04 ccc6e87d482b 3 days ago 64.2MB4. 実行
上記imageを使ってコンテナをたてる。
$ docker run --net host --name test -v //c/Users/<User Name>/docker:/wrk -it u18_py37 bashおわりに
とりあえず環境構築自体はこんな感じでしょうか。
ここのやり方良くない等、ご指摘あればよろしくお願いします。
作った環境で初めてwebAPI叩くコード書いたりするのですが、それはまたそのうち別記事で。
- 投稿日:2020-01-19T21:59:56+09:00
Autosar文書を読む(準備)
自動車用のOS、通信規約、道具類などを規定しているAutosarは、ISO OSEKとISO/IEC POSIXの自動車産業における設計例である。
WTO/TBT協定によれば、国際的な調達は、ISO, IEC, ITUなどの国際規格を仕様記述の出発点として参照することを推奨している。
Autosarも、ISO OSEK及びISO/IEC POSIXを参照している。自動車分野はISOのTC22で審議しておりISOの単独文書。POSIXはIT分野でISO/IEC JTC1 SC22で審議しておりISOとIECの合同文書。
IEEEはEthernet, Wi-Fiなどを規格化し、ISO, IECと協力して関連規格を出版している。ISO, IEC, IEEEの共同文書も相当数ある。
SAEはアメリカの自動車技術会相当の組織。misraはイギリスにある自動車ソフトウェア団体。
それぞれの名称の出現頻度は下記。
standard count organization osek 176 ISO TC22 POSIX 96 ISO/IEC JTC1 SC22 ISO 2297 IEC 138 IEEE 300 sae 723 Society of Automotive Engineers misra 410 背景
Toppersプロジェクトで ISO Osekに対応したオープンソースを発行する事業に参加し、標準化、安全分析、MISRA C適合、訓練などに参加してきた。また、TOPPERSプロジェクトのAutosar環境であるATKを実機なしで模擬試験できるソフトウェアを追っかけている。
TOPPERS/ATK2カーネル向け実機レス環境(athrill2)
https://qiita.com/kanetugu2018/items/75dadc340f3db2a344abOS及びC言語及びTCP/IP通信ソフトウェアのC言語規格およびPOSIXへの適合試験を行ってきた。
Posix Test Suite docker downloads, tar, install
https://qiita.com/kaizen_nagoya/items/f1e24be04a2405ede00fOsekに基づいたAutosarへの対応においてもいくつかの視点で評価を行ってきた。
当初は、現在のclassic版だけであったが、Adaptive版についてもPOSIX対応の延長で対応してきた。初めて検討する分野では、まず参考文献の参考文献を洗い出し、入手可能性を検討する。
参考文献の入手は時間がかかったり、お金がかかたりすることがある。そのため、最初に着手しておかないと、費用の見積もりを過小評価してしまうかもしれないからである。参考文献の参考文献の入手性を確認したら、入手できた範囲の文献の用語頻度一覧と、略語集を作る。
今回、用語頻度一覧から着手しているのは、これまでに一度は入手可能性を確認した文書であることと、ISO/IEC JTC1 SC7から、ISO TC22への国際的なliaison(情報交換担当)として両委員会の公式文書をReviewしてきた過程において、各文書のNormative Referenceの入手可能性を検討してきた経緯があるからである。
文書入手
Autosar単語帳(作業中)
https://qiita.com/kaizen_nagoya/items/0927727a94b157df2df8目次から一つづつファイルを入手しようとすると、最新ではない文書にぶつかったり、文書が一覧に見当たらないという現象に出会った。
そこで、上記URLの最後に記載した、一覧で一括入手できる方法によった。
PDFのText変換
辞書作成のために、PDFをText変換した。
プログラミングの用語一覧の場合には、数字や_などの記号で、変数名、関数名、定数名で使うことができる文字を含んだ、なるべく長い文字列で一覧を作成する。
標準文書では、数字や_, -, などの記号を省略し、単語として同じ意味で使っている言葉はなるべく頻度を集計できるような方向での処理を行う。ただし、複数形、過去形などの変化系はあえて統合せず、文字列として現れるままで集計している。
これは、過去の難度かの複数形、過去形などの統合の処理では、別の意味で使っている用語を、文字列の並びがたまたま同じになるために同一の語として集計してしまったり、結果として分析のための精度が作業量に比較して向上しないという経験則による。
作業はdocker上で行った。どこからでも作業を再開できるようにdocker hubに保存している。
用語頻度
Autosar 単語検索 略号等
https://qiita.com/kaizen_nagoya/items/f8cb1295104b7d58363d英語(38) 複合語と複数の単語の一分類 https://qiita.com/kaizen_nagoya/items/219fd0bde3731f0881ed
作業記録 Autosar単語帳の分割の抜け漏れ
https://qiita.com/kaizen_nagoya/items/15b4011a68ce0ba81e6e略号一覧
略号のfull spellingの確認のため、全文書の略号一覧を統合中である。
参考文献一覧の作成と一緒に作業中。Autosar文書、参考文献、略号一覧(作成中)
https://qiita.com/kaizen_nagoya/items/2325b0156bc7fcf5a96d普段はこの作業から始めるが、今回は逆順である。
これまで、複合語と複数の単語に分類することは、あまり意識してこなかった。
今回は、プログラミングですぐに用いることを想定するのではなく、プログラミングの変数名などを含むため、複合語を分解し、技術的な概念分布を検討することを目的とすることにした。英語(2) まぎらわしい、間違えやすい、行き違いの多い略号worst 10(候補24)
https://qiita.com/kaizen_nagoya/items/0bff5dbb72208053489b英語(3) 仮説・検証(88)用語の衝突(用語・用例募集中)
https://qiita.com/kaizen_nagoya/items/6a8eb7ffaa45eeb16624道具類
作業経過で利用している道具類は次の通りである。それぞれの作業で出たエラー類は別記事として整理している。
docker
今日のdocker error : Error response from daemon: error while creating mount source path
https://qiita.com/kaizen_nagoya/items/1ff3550c4ef1c545ce12ubuntu
bash
今日のbashエラー:No such file or directory(解決)
https://qiita.com/kaizen_nagoya/items/4bcf2ebdce3b475a808ashell の種類と版
https://qiita.com/kaizen_nagoya/items/ab715ffeceb8617f11capdftotext
PDFファイルの文字誤変換
https://qiita.com/kaizen_nagoya/items/49ce6e8cead58c646534sed
今日のsed error:unknown option to `s'
https://qiita.com/kaizen_nagoya/items/8e8c4efdb6869f965b54awk
表計算ソフト
grep
grep 操作間違いなどhttps://qiita.com/kaizen_nagoya/items/2f14e895175908c296ca
macOSテキストエディタ, mi.app
四角い領域の切り取り、切り貼り
https://qiita.com/kaizen_nagoya/items/ba3661d4e224acdf1b04参考文献(reference)
Autosar Guidelines C++14 example code compile list(1-169)
https://qiita.com/kaizen_nagoya/items/8ccbf6675c3494d57a76#_reference-3a2b9cfd1b05f6a444c2Autosarの課題
https://qiita.com/kaizen_nagoya/items/617d10b0e34143030600英語(1) プログラマが知っているとよい英単語の語源
https://qiita.com/kaizen_nagoya/items/9de6d47c47e2c211222b文書履歴(document history)
ver. 0.01 初稿 20200119
ver. 0.02 URL追記 20200120
- 投稿日:2020-01-19T21:28:57+09:00
DockerでMediaWikiとVisualEditorを入れたログ
DockerでMediaWikiを入れたときのメモ。Docker初めて触った。
- 扱うもの
- MediaWiki(1.34.0)の導入(Dockerでごり押す)
- parsoidの導入(Dockerでごり押す)
- VisualEditorの導入
- いくつかの拡張機能の導入
- 扱わないもの
- MySQL
- 既に入っている状況下に構築したので
- RESTBase
- むずすぎて投げた
環境
- ホストOS
- Ubuntu 18.04.3 LTS
手順
すべてsudo権限下で行ったが、別に要らない可能性もある(知らない)。
Dockerインストール済みを想定。
ホスト:dir#
とは、ホストマシン上のディレクトリdir
でsudo権限でbashコマンドを実行するの意味。ディレクトリは省略された場合どこでコマンドを実行してもよい。MediaWikiのDockerイメージを見つける
ホスト:# docker search mediawiki NAME DESCRIPTION STARS OFFICIAL AUTOMATED mediawiki MediaWiki is a free software open source wik… 201 [OK] synctree/mediawiki Docker packaging for MediaWiki. Based on off… 79 [OK] wikimedia/mediawiki MediaWiki is the wiki package used by Wikipe… 50 kristophjunge/mediawiki MediaWiki with VisualEditor plugin and Parso… 29 [OK] 以下省略とりあえず安直に
mediawiki
を使うことにした。既に色々入っているイメージとかあるみたいだけど、最初に入れたこれで最後まで要求が満たされたので結局これを採用した。とりあえずMediaWikiのサーバーを建ててみる
まずは目当てのイメージをダウンロードしてくる
別にやらなくてもrun時に自動的にダウンロードされるかもしれない。
ホスト:# docker pull mediawikiコンテナを新造して立ち上げる
ホスト:# docker run -d --net=host --name mw mediawiki
-d
を付けることでバックグラウンドで起動する。
--net=host
でホストのコンピュータと同じネットワーク上で起動する。今回は同マシン上で建っているparsoidサーバーにアクセスするためにこれを指定した。
--name mw
で名前をmwにする。名前は何でもいい。省略すると適当に変な名前が振られる。中に入ってみる
このコマンドで、Dockerの中でbashを起動できる。
docker exec -it mw bashコンテナ内のファイルシステムをホスト上で直接書き換えられるようにしてみる
おもむろにホスト側にjsonを色々できるjqをインストールする。
ホスト:# apt install jq
- jq コマンドを使う日常のご紹介 - Qiita https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af
さっきrunしたmwの情報を以下のコマンドで見れる。
ホスト:# docker container inspect mwこれを実行するとJson形式のデータが得られるので、次のようにディレクトリを取り出せる。
ホスト:# docker container inspect mw | jq -r '.[0].GraphDriver.Data.MergedDir' /var/lib/docker/overlay2/c39bc935abfaaedc65e96d7b6cb7985db77687f7d62b867e4a1a6bd059c94734/mergedmergedの中はコンテナの内部からリアルタイムに参照されるルートディレクトリである。
ホスト:/var/lib/docker/overlay2/c39bc935abfaaedc65e96d7b6cb7985db77687f7d62b867e4a1a6bd059c94734/merged# ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr varポート変更
エディタとか色々と入っていなくて萎えるので、ホスト側のファイルシステム上に見えているコンテナのファイルシステムの本体を直接書き換えて済ます。
ホスト:merged# nano etc/apache2/ports.conf好きなように変えることができる。
編集- Listen 80 + Listen 12345Dockerの機能の方でポートフォワーディングもできるみたいだけど、理解するのが面倒なので置いておく。
コンテナ再起動
docker restart mw接続
アクセスしてみるとこんなのが出る
インストール
この辺はウィザードに従ってうまいことやる。Dockerで環境ごと入れたのでそんなに困らないんじゃないかと思う。
データベースはホスト上で既に動いているMySQLを使用したので「MariaDB、MySQLまたは互換製品」を選択。
「データベースのホスト」には
127.0.0.1
を指定。データベースとユーザの用意は以下の情報に従って作成する。
- Manual:MediaWiki のインストール - MediaWiki https://www.mediawiki.org/wiki/Manual:Installing_MediaWiki/ja#MariaDB/MySQL
> CREATE DATABASE wikidb; > CREATE USER 'wikiuser'@'localhost' IDENTIFIED BY 'password'; > GRANT ALL PRIVILEGES ON wikidb.* TO 'wikiuser'@'localhost' WITH GRANT OPTION;「オプション→拡張機能」欄はよくわからないので全部チェックを入れた。
全部うまくいくと「データベースは正常にセットアップされました」と出て
LocalSettings.php
をダウンロードさせられるので、ダウンロードして配置する。配置は、面倒なのでTerapadで開いてコピーしたあと、配置先のファイルをnanoで開いてコマンドプロンプトに右クリックで貼り付けた。
ホスト:merged# nano var/www/html/LocalSettings.phpインストールが成功していればトップページが次のようにWikiらしい表示になる。
いくつかの拡張機能のインストール
「特別ページ→バージョン情報→インストール済み拡張機能」を見てみる。ここがハイフンになっている奴が導入されていないという声が上がったので、インストールする。
とりあえず欲しいものを手動で手あたり次第ダウンロードし、圧縮ファイルを一つのディレクトリにまとめてホストコンピュータに転送する。
仮に
~/mediawiki
にまとめた場合、以下のようにすると拡張機能のインストールが完了する。ホスト:merged# d='~/mediawiki' ホスト:merged# for f in $(ls -1 "$d"); do tar -xzf "$d/$f" -C var/www/html/extensions; doneVisualEditorを導入する
VisualEditorの導入は闇である。しかし、導入に成功した時の恩恵も大きい。
VisualEditorを利用するにはparsoidというサーバー用にポートを1個確保しなければならない。これはマシン内でのみ通信されるので、ポートを外部に向けて公開する必要はない。
- 参考
- MediaWikiにVisualEditorをインストールする | 東北ギーク http://tech.respect-pal.jp/mediawiki_install/
VisualEditorのインストール
いきなりVisualEditorをインストールする。
ホスト:marged/var/www/html/extensions# git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/VisualEditor.git ホスト:marged/var/www/html/extensions# cd VisualEditor ホスト:marged/var/www/html/extensions/VisualEditor# git checkout remotes/origin/REL1_34 ホスト:marged/var/www/html/extensions/VisualEditor# git submodule update --initインストール完了。
VisualEditorの設定
共通設定ファイルを編集する。
ホスト:marged/var/www/html# nano LocalSettings.php末尾に追加wfLoadExtension('VisualEditor'); $wgDefaultUserOptions['visualeditor-enable'] = 1; $wgHiddenPrefs[] = 'visualeditor-enable'; $wgVirtualRestConfig['modules']['parsoid'] = [ 'url' => 'http://localhost:12346/', 'domain' => 'localhost', ];ここで、12346はparsoidのポート番号である。domainにはポートまでは書かない。URLの末尾には/を入れる。
これで動いた。
parsoidを建てる
parsoidもDockerで建てる。
# docker search parsoid NAME DESCRIPTION STARS OFFICIAL AUTOMATED thenets/parsoid Containerized MediaWiki parsoid service. 4 benhutchins/parsoid Container to run MediaWiki's Parsoid 2 [OK] formwandler/parsoid Parsoid image for the VisualEditor of MediaW… 1 irasnyd/parsoid Docker container of the Mediawiki Parsoid ap… 1 [OK]よくわからんがとりあえず
thenets/parsoid
を使う。
- thenets/parsoid - Docker Hub https://hub.docker.com/r/thenets/parsoid
コンテナを製造。公式にはrun時のパラメータで色々できることが書いてあるが、それをするとポートの変更方法がなんかよくわかんなかったので使わない。
ホスト:# docker run -d --net=host --name ps thenets/parsoid:0.10parsoidを設定
thenets/parsoidの中では全然コマンドが打てないのでこっちもファイルシステムに直接アクセスする。
docker container inspect ps | jq -r '.[0].GraphDriver.Data.MergedDir'中に入るとこうなっている。
ホスト:merged# ls bin dev etc home lib media mnt opt proc root run run-parsoid.sh sbin srv sys tmp usr var
run-parsoid.sh
を編集するホスト:merged# nano run-parsoid.sh先頭付近を編集#!/bin/bash + PARSOID_DOMAIN_localhost=http://localhost:12345/api.php + set -e中腹付近を編集# Allow override of port/interface: - serverPort: 8000 + serverPort: 12346 #serverInterface: '127.0.0.1'ここで、12345はMediaWikiのポート番号、12346はparsoidのポート番号である。
あとは再読み込みする。
docker restart psVisualEditorの導入が完了
これでVisualEditorの導入が完了した。
Parsoidとの連携がうまくいっていないとここで404が出たとか言われた。そのときはURLの指定が間違っていた。
「ブラウザ→MediaWiki API→Parsoid」のうちどの部分の呼び出しが404になっているのか注意しなければ、どこが間違っているのかが把握できない。
- 投稿日:2020-01-19T21:27:38+09:00
Manage SSL/TLS certificate with certbot + nginx on Ubuntu18.04
certbot作法について、2020/1/19時点で調べた結果をまとめておく。
nginxの使用を想定。HTTPを使用するHTTP-01方式での証明書取得についてのみ記述する。
OS: Ubuntu18.04
WebServer: Nginxオンラインドキュメント
Ubuntu18.04での流れ: https://certbot.eff.org/lets-encrypt/ubuntubionic-nginx
User Guideにコマンド詳細: https://certbot.eff.org/docs/
証明書管理の流れ
サブコマンドで書くと
- register: アカウント登録
- certonly: 証明書取得
- install: WebServer設定
- renew: 証明書更新
- revoke: 証明書の失効
- unregister: アカウントの無効化
という流れになる。
1.は初回に一度だけ実行する。
2.,3.は証明書を取得するドメインに応じて実行する。
4.を自動化して証明書更新をし続ける。
5.,6.は必要に応じて行う。インタラクティブモード
register,certonly,installでは、必須オプション不足時にインタラクティブで入力を促してくる。
初回のみの作業なので、インタラクティブモードを活用するのもあり。テストサーバーの指定
--test-certオプションをつける。以降のコマンドサンプルにはつけて記述する。
テストサーバーを利用する際は、本番用ドメインと競合しないように
test-cert.examle.com
のようなテスト用サブドメインを用意して試すのがよい。パッケージインストール
Cerbot PPAを利用する。
sudo apt-get update sudo apt-get install software-properties-common sudo add-apt-repository universe sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install certbot python-certbot-nginxcertbot register: アカウント登録
とばした場合、
certbot certonly
実行時に行われる。% certbot --test-cert register Saving debug log to /var/log/letsencrypt/letsencrypt.log # Email address登録 # 登録しない場合は、 --register-unsafely-without-email をつける。 Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): admin@example.com # 利用規約の同意。同意必須。 # --agree-tos をつけることで同意にしてスキップ可能。 # テストサーバーの場合、https://~staging~ となる。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must agree in order to register with the ACME server at https://acme-staging-v02.api.letsencrypt.org/directory - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (A)gree/(C)ancel: A # EFFとのメールアドレス共有を許可するか。 # --eff-email: 共有許可 # --no-eff-email: 共有しない - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: N IMPORTANT NOTES: - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal.オプション指定でノンインタラクティブで実行可能。
# Email登録なしでのコマンド例 certbot --test-cert --noninteractive register --register-unsafely-without-email --agree-toscertbot certonly: 証明書取得
certbot --test-cert certonly Saving debug log to /var/log/letsencrypt/letsencrypt.log # 取得方法を指定する。後述。 # nginx: --nginx # standalone: --standalone # webroot: --webroot How would you like to authenticate with the ACME CA? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1: Nginx Web Server plugin (nginx) 2: Spin up a temporary webserver (standalone) 3: Place files in webroot directory (webroot) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 1 Plugins selected: Authenticator nginx, Installer None # ドメイン入力 # --domain DOMAIN Please enter in your domain name(s) (comma and/or space separated) (Enter 'c' to cancel): test-cert.example.com Obtaining a new certificate Performing the following challenges: http-01 challenge for test-cert.example.com Waiting for verification... Cleaning up challenges # Congratulations!で成功 IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/test-cert.example.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/test-cert.example.com/privkey.pem Your cert will expire on 2020-04-18. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew"/etc/letsencrypt/live/{domain_name}/ に最新の証明書および秘密鍵へのリンクが作成される。
WebServerはこのシンボリックリンクを参照するようにする。取得方法について
certbot certonly
で問われる取得方法。
それぞれで作業が異なるので、nginx-plugin, standalone, webrootについて書く。nginx-plugin
--nginx
オプション指定で動作。
nginxの設定変更無しに証明書の取得・更新が可能。
また、証明書更新時にはnginxのリロードも行う。
nginxが常駐するインスタンス内でcertbotを動かす場合に使用できる。
apt install python-certbot-nginx
などでプラグインのインストールが必要。standalone
--standalone
オプション指定で動作。
certbot自身がHTTPサーバーとなって作業する。
80番ポートを使うので、nginxが80番ポートを使用してる場合は、証明書取得・更新時にはnginxを停止しておく必要がある。webroot
--webroot
オプション指定で動作。
HTTPサーバーの役割をnginxなどに任せて作業する。
http://test-cert.example.com/.well-known/acme-challenge/
配下にファイルを作成するので、/.well-known/acme-challenge/パスに対応するサーバーインスタンス内でのディレクトリを教える必要がある。例えば、以下のようなnginx.confであれば、webrootのディレクトリ指定には、/var/www/htmlを指定する。
# example server { listen 80; location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; root /var/www/html; } }certbot install: WebServer設定
WebServerのVirtualHostやhttp->https redirectなどの設定を行う。
nginx-pluginが必要。
certbot install
の代わりに、nginx.confを自分で書き換えてもよい。% certbot --test-cert install Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator None, Installer nginx # VirtualHost選択 Which certificate would you like to install? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1: test-cert.example.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Press 1 [enter] to confirm the selection (press 'c' to cancel): 1 Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/default # http->https redirect有無 Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1: No redirect - Make no further changes to the webserver configuration. 2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for new sites, or if you're confident your site works on HTTPS. You can undo this change by editing your web server's configuration. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2 Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/defaultcertbot certificates: 証明書一覧
取得済み証明書を確認する場合に使用。
certbot --test-cert certificates Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Found the following certs: Certificate Name: test-cert.example.com Domains: test-cert.example.com Expiry Date: 2020-04-18 09:24:30+00:00 (INVALID: TEST_CERT) Certificate Path: /etc/letsencrypt/live/test-cert.example.com/fullchain.pem Private Key Path: /etc/letsencrypt/live/test-cert.example.com/privkey.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
httpsアクセスできることを確認
httpsでアクセスしてみる。
テストサーバーで発行された証明書は、無効な証明書となっている。certbot renew: 証明書の更新
更新期限30日未満の証明書のみが更新の対象となる。
# --force-renewalをつけると期限30日前でも更新可能だが、基本使わない % certbot --test-cert renew Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Processing /etc/letsencrypt/renewal/test-cert.example.com.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cert not yet due for renewal - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The following certs are not due for renewal yet: /etc/letsencrypt/live/test-cert.example.com/fullchain.pem expires on 2020-04-18 (skipped) No renewals were attempted. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -更新の自動化
apt install certbot
で、cronもしくはsystemd timerで行われるようになる。
cronの設定ファイルには、systemdが無い場合に動作するようにコマンドが書かれている。証明書取得方法に応じて、書き換えが必要となる。
nginx−plugin
プラグインによって、nginx -s reloadの実行がされるので設定書き換えは不要。
standalone
nginx停止が必要なので、 --pre-hook,--post-hookを使う。
# /usr/sbin/service利用時 certbot -q renew --pre-hook "/usr/sbin/service nginx stop" --post-hook "/usr/sbin/service nginx start" # supervisord利用時 certbot -q renew --pre-hook "/usr/bin/supervisorctl stop nginx" --post-hook "/usr/bin/supervisorctl start nginx"webroot
--post-hookでnginx -s reloadを使用する。
certbot -q renew --post-hook "/usr/sbin/nginx -s reload"certbot revoke: 証明書の失効
revokeすると、証明書など関連ファイルが削除される。
% certbot --test-cert revoke --cert-path /etc/letsencrypt/archive/test-cert.example.com/cert1.pem Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you like to delete the cert(s) you just revoked? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es (recommended)/(N)o: Y - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Deleted all files relating to certificate test-cert.example.com. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Congratulations! You have successfully revoked the certificate that was located at /etc/letsencrypt/archive/test-cert.example.com/cert1.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
certbot unregister: アカウント削除
% certbot --test-cert unregister Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Are you sure you would like to irrevocably deactivate your account? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (D)eactivate/(A)bort: D IMPORTANT NOTES: - Account deactivated.
certbot同時実行時の安全性について
同時実行できない。安心。
Lock Files: https://certbot.eff.org/docs/using.html#id5This means that by default two instances of Certbot will not be able to run in parallel.
- 投稿日:2020-01-19T17:46:11+09:00
Synology DockerでJenkinsをセットアップするには
前提
Synology NAS DS218+で遊んでいます。
NAS :Synology DiskStation 218+
RAM:10GB(2GB+8GB)
HDD:4TB + 3TB概要
Jenkins-blueoceanをセットアップした時の初期パスワードの確認方法がわからなかったのが、やっと分かったのでメモ
ローカルの場合
ローカルでの初期パスワードの確認は、terminalで
cat $HOME/jenkins_home/secrets/initialAdminPassword
を入力し、表示されるパスワードを利用します。Synology Docker Jenkinsの場合
Synologyとsshで接続してこのコマンドを入力しても見つかりません。
Synology Dockerのコンテナから、セットアップしたJenkinsの詳細を表示し、詳細画面の[概要][プロセス][ログ][端末]から「端末」を選択。
作成ボタンを押下したら表示される[bash]を選択。
terminalが表示されるので、
cat var/jenkins_home/secrets/initialAdminPassword
を入力し、表示されるパスワードを利用します。
- 投稿日:2020-01-19T17:13:38+09:00
Kubernetesの構築
kubernetes-construction
常駐先の社内勉強会用の記事でしたが、全体に公開してみます。(全体公開は初です。)
こうした方がいいよがあればコメントください。
$
マークはコピペしやすい様にあえて付けていません。Kubernetes + Nvidia Docker の構築(まだ途中です。)
検証済み環境
OS ARCH docker Ver. ESXi Ubuntu 18.04 amd64 Docker version 19.03.5, build 633a0ea838 6.7 Custom ISO Ubuntu 18.04 ppc64le Docker version 18.06.1-ce, build e68fc7a None ppc64le はIBM Power System AC922 POWER9で検証
コンテナイメージはそれぞれのアーキテクチャに合わせる必要があります。
docker のインストール(docker-ce)
既存のアンインストール
sudo apt-get remove docker docker-engine docker.io containerd runc
docker-ce のインストール
bash# パッケージの更新 sudo apt-get update # 必要モジュールのインストール sudo apt-get install -y \ 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 # リポジトリの追加 # amd64 sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" # ppc64le sudo add-apt-repository \ "deb [arch=ppc64el] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" # パッケージの更新 sudo apt-get update # dockerのインストール sudo apt-get install -y docker-ce # ユーザーの追加 sudo usermod -aG docker $USER # dockerサービスの自動起動 sudo systemctl enable docker # dockerサービスの起動 sudo systemctl start docker補足情報
bash# インストール可能なリスト apt-cache madison docker-ce # バージョンを指定してインストール sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.iokubernetes インストール
リポジトリにキーの登録
bashcurl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"リポジトリの更新
bashsudo apt update sudo apt install -y kubeadmスワップ OFF
bash## 都度適応? ## /etc/fstabを削除すると泣くことになる -> なぜかdockerが立ち上がらなくなる sudo swapoff -akubeadm でセットアップ
bashsudo kubeadm init --pod-network-cidr=10.244.0.0/16kubernetes config の追加
bashmkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/configiptables の編集
sudo sysctl net.bridge.bridge-nf-call-iptables=1
これをしないと
core-dns
の pod が起動しないflannel.yaml の追加
kubectl -f flannel.yml
LoadBranser の構築
metallb.yamlを適用する
kubectl apply metallb.yaml
LAN 内の IP に割り振る yaml を apply する
metallb-config.yaml--- apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: default protocol: layer2 addresses: - xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx # この部分をLAN内のIPに変更するMaster Nodes にもデプロイする場合(シングルマスタノード構成の場合とか)
kubectl taint nodes 名前空間 node-role.kubernetes.io/master:NoSchedule-
名前空間
部分はkubectl get node
で取得できるName
を設定(Master の Name)bashkubectl describe node node名 # ~~ 中略 ~~ Taints: <none> # ~~ 中略 ~~ # 上記になっていることを確認Master へ Node を追加する
bashsudo kubeadm join xxx.xxx.xxx.xxx:6443 --token xxxxxx.xxxxxxxxxxxxx --discovery-token-ca-cert-hash sha256:xxxxxxxMaster を構築した時に最後に表示される
--token
--discovery-token-ca-cert-hash
を設定するToken が不明になった場合
bash# tokenが不明になった場合は再度発行すれば良い kubeadm token create --print-join-commandNode が追加されたか確認
bashkubectl get nodes NAME STATUS ROLES AGE VERSION Master Ready master 3m11s v1.17.1 Node1 Ready <none> 2m10s v1.17.1DashBorad(v2.0.0-rc2) のデプロイ
kubernetes リポジトリから直接デプロイする場合はクラスタ内部からしかアクセス出来ないため、
NodePort を設定したrecommended.yaml
をデプロイする。
ただし、リポジトリから直接デプロイし、NodePort を設定しても
issue にある様なエラーが発生するためここではすでに用意しているdashboard/recommended.yamlを使用する
また、その際に証明書の設定をする必要があるため、下記を実施すること自己証明書の発行
bashmkdir certs openssl req -nodes -newkey rsa:2048 -keyout certs/dashboard.key -out certs/dashboard.csr -subj "/C=/ST=/L=/O=/OU=/CN=kubernetes-dashboard" openssl x509 -req -sha256 -days 365 -in certs/dashboard.csr -signkey certs/dashboard.key -out certs/dashboard.crtすでに定義されている分を削除(直接デプロイした場合)
bash# 削除 kubectl -n kubernetes-dashboard delete secret kubernetes-dashboard-certs証明書を pod から使用できる様にする
- certs/dashboard.crt
- certs/dashboard.csr
- certs/dashboard.key
上記の証明書ファイルを Secret オブジェクトへ設定できる形にする
bash# base64形式で設定する必要があるのでbase64コマンドで設定する # それぞれのファイルで実施する # certs/dashboard.crt # certs/dashboard.csr # certs/dashboard.key cat certs/dashboard.crt | base64 cat certs/dashboard.csr | base64 cat certs/dashboard.key | base64recommended.yaml の編集
recommended.yaml--- apiVersion: v1 data: dashboard.crt: base64に変換された.crtファイルを記述 dashboard.csr: base64に変換された.crsファイルを記述 dashboard.key: base64に変換された.keyファイルを記述 kind: Secret metadata: name: kubernetes-dashboard-certs namespace: kubernetes-dashboard labels: k8s-app: kubernetes-dashboard type: Opaqueapply する!
kubectl apply -f dashboard/recommended.yaml
ログイン用のトークンを設定
ログイン画面には token or kubeconfig が求められます。
今回は Token を用いてログインする方法を記載します。admin-user.yamlapiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboardbashkubectl apply -f admin-user.yaml kubectl get secret -n kubernetes-dashboard | grep admin admin-user-token-xxxx kubernetes.io/service-account-token 3 kubectl describe secret -n kubernetes-dashboard admin-user-token-xxxxx表示された
token
をコピーし、
トークン
を選択し、トークンを入力
にペーストし、サインインを行う。
- 投稿日:2020-01-19T16:40:49+09:00
Docker+Laravelでタスクスケジューラ
目的
通常サーバのタスクスケジューラはcronにて行うが、
- 少し面倒であること
- Laravelにタスクスケジューラの機能があること
から、画面を作成して画面経由でタスクスケジュール設定を行えるものを作成してみる。
前提
下記の環境で実装した。
- PHP7.1.x
- Laravel6.x+AdminLTE3
- PostgreSQL11.4
- Docker phpfpm
サンプル仕様
サーバのタスクスケジュールのため、画面操作するためにログインが必要とした。
タスク自体は別途実装済みであるとして、タスク名と実行スケジュールを設定する画面を
用意する。
タスクの実行はLaravelにタスクスケジューラをcron経由で実行するものとして、タスクスケジューラの設定を先の画面で設定したものを反映させるものとする。タスクの実装
詳細は省略するが、タスクの雛形をartisanで作成できる。
% php artisan make:command タスク名とりあえず、タスクが動いたか確認したいため、下記のタスクを実装した。
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; class Shout extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'command:shout'; 〜省略〜 /** * Execute the console command. * * @return mixed */ public function handle() { Log::info("start shout!!"); } }見ての通り、実行されたらログが出力されるだけのタスクである。
モデル定義
定義するモデルはScrapingCommandである。
migrateの内容を下記に示す。?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateScrapingCommandsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('scraping_commands', function (Blueprint $table) { $table->bigIncrements('id'); $table->string("name",200); $table->string("cmd",200); $table->integer("cron1")->nullable(); $table->integer("cron2")->nullable(); $table->integer("cron3")->nullable(); $table->integer("cron4")->nullable(); $table->integer("cron5")->nullable(); $table->integer("flg")->default(0); $table->softDeletes(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('scraping_commands'); } }画面実装
ログイン画面
タスク一覧画面
登録されているタスクの一覧表示している。
タスクスケジュールはcronと同じ形式である。スケジュールとは別に有効/無効の設定が可能である。
タスク設定画面
タスクの設定を行う。コマンド名はartisanで使用するコマンド名(\$signatureに設定しているもの)を設定する。
設定内容はScrapingCommandモデルに保存される。
Laravel側のスケジュール定義
LaravelのタスクスケジュールはApp\Console\Kernelのscheduleメソッドで定義するため、
同メソッドを下記のように修正した。<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Support\Facades\Log; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; use App\ScrapingCommand; class Kernel extends ConsoleKernel { 〜省略〜 /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $lst = ScrapingCommand::where("flg",1)->get(); foreach($lst as $rec) { Log::info("cmd:".$rec->cmd); Log::info("cron:".$rec->cronStr()); $schedule->command($rec->cmd)->cron($rec->cronStr()); } } 〜省略〜 }Cron側の設定
Cron側はLaravelのタスクスケジューラを実行するだけなので、
* * * * * /usr/local/bin/php /svr/app/artisan schedule:run >> /var/log/cron.log 2>&1 (注)/svr/appはLaravelをインストールしたディレクトリ本来はcrontab -e で上記のファイルを作成することになるが、今回はDockerなので、
rootファイルとして作成しておく。以上で、要望を実装済みであるが、今回はDockerで実装したため、コンテナ上でcronのインストールが必要になる。
そこで、cronのインストールはDockerイメージ作成時に行う。よってDockerファイルは
FROM php:fpm # For composer RUN apt-get update \ && apt-get install -y gcc make zlib1g-dev libzip-dev libpng-dev unzip libmcrypt-dev libjpeg-dev libfreetype6-dev \ && docker-php-ext-install zip \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include \ && docker-php-ext-install -j$(nproc) gd # Install composer RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ && php composer-setup.php \ && php -r "unlink('composer-setup.php');" \ && mv composer.phar /usr/local/bin/composer # Set composer environment ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer ENV PATH $PATH:/composer/vendor/bin # Install laravel installer RUN composer global require "laravel/installer" # PHP's DB setting RUN apt-get update \ && apt-get install -y libpq-dev \ && docker-php-ext-install pdo_mysql pdo_pgsql # Install Node.js RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - \ && apt-get update \ && apt-get install -y nodejs RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime RUN apt-get install -y cron RUN mkdir /debugbar RUN chmod go+w /debugbar WORKDIR /svrとした。
次にcrontabの登録とcron起動が必要になるが、今回は手動で行うものとした。
よって、上記で作成したイメージからコンテナを起動して、コンテナ上で% cp root /var/spool/cron/crontab % service cron startを実行する。
rootファイルはあらかじめ/svrにコピーしておくこと。考察
cronの設定って結構面倒なものである。何よりわざわざサーバにログインして作業しないと行けないのである。
この仕組みだと、画面で設定するだけなので大分楽である。タスクはLaravel上で動くため、
DB接続とかログ出力とかの考慮が必要なくなる。問題点は
- crontabの設定とcronの起動をコンテナ起動後手動で行わなければならない。
Dockerイメージでcronの起動もできるらしいが、今回は割愛した- 5分毎等のスケジュールに対応できてない
これは実装の問題であるが。。。サンプルで実装したプロジェクトはGitHubにアップしたので、必要であれば参照していただきたい。
- 投稿日:2020-01-19T15:28:58+09:00
pip環境のdockerでjupyter notebookを使いたかった(opticspy)
背景
- Dockerで環境構築してpythonコードを書く際,画像の結果を見るのにjupyter notebookが楽
- opticspyというモジュールを使ったシミュレーションをしようとした時,pip installが前提となっていた
- Jupyterは普段anaconda環境下で使っているので,どうしたら良いか調べながら対処した
Dockerfile
FROM continuumio/anaconda3:latest RUN apt-get update && apt-get upgrade -y \ && apt-get install -y \ git \ make \ build-essential \ libssl-dev \ zlib1g-dev \ libbz2-dev \ libreadline-dev \ libsqlite3-dev \ wget \ curl \ llvm \ libncurses5-dev \ libncursesw5-dev \ xz-utils \ tk-dev \ libffi-dev \ liblzma-dev \ vim RUN conda create -n p37 python=3.7 pip実行コード
terminal.sh$ docker run -it -p 8881:8881 -v /hogehoge/:/mnt/ --name pip_in_conda pip_in_conda:1.0 $ source activate p37 $ pip install jupyter $ pip install environment_kernels $ jupyter notebook --generate-config $ vim /root/.jupyter/jupyter_notebook_config.pyvimで追記する内容は以下の通り
jupyter_notebook_config.pyc.NotebookApp.kernel_spec_manager_class='environment_kernels.EnvironmentKernelSpecManager' c.EnvironmentKernelSpecManager.env_dirs=['/opt/conda/envs/']terminal.sh$ pip install cffi $ pip install numpy $ pip install git+git://github.com/Sterncat/opticspy.git@master $ pip install pyyaml $ jupyter notebook --port 8881 --ip=0.0.0.0 --allow-rootopticspyのサンプルコード実行の様子

- 投稿日:2020-01-19T14:24:47+09:00
DockerでTesseractの環境を構築してみた。。。
はじめに
Googleが開発したTesseract(テッセラクト)の環境をDockerを使用して作成します。
目次
- aptでインストール
- Gitからソースを持って来てコンパイル
- まとめ
1. aptで簡単にインストール
公式のGitHubを参考にします。
FROM ubuntu:18.04 RUN apt-get update \ && apt-get upgrade -y \ && apt-get install -y \ tesseract-ocr \ libtesseract-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*Dockerfileのビルドdocker build --rm -f "tesseract/Dockerfile" -t tesseract:apt-install "tesseract"ビルドが完了したらコンテナを立ち上げます。
tesseract 4.0.0-beta.1
がインストールされていることが確認できます。tesseractのコンテナroot@99207ebd4115:/# tesseract -v tesseract 4.0.0-beta.1 leptonica-1.75.3 libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 1.5.2) : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.3.0 Found AVX2 Found AVX Found SSE root@99207ebd4115:/#2. Gitからソースを持って来てコンパイル
次に公式のgitからソースコードを持って来てコンパイルしましょう。
公式のGitHubを参考にします。
ビルドに20分ほどかかります。FROM ubuntu:18.04 RUN apt-get update \ && apt-get upgrade -y \ && apt-get install -y \ automake \ ca-certificates \ g++ \ git \ libtool \ make \ pkg-config \ wget \ libicu-dev \ libpango1.0-dev \ libcairo2-dev \ && apt-get install -y --no-install-recommends \ asciidoc \ docbook-xsl \ xsltproc \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* WORKDIR /opt ENV TESSERACT_VER="4.1" RUN wget http://www.leptonica.org/source/leptonica-1.79.0.tar.gz \ && git clone -b ${TESSERACT_VER} https://github.com/tesseract-ocr/tesseract.git --single-branch \ && tar -zxvf leptonica-1.79.0.tar.gz WORKDIR /opt/leptonica-1.79.0 RUN ./configure \ && make \ && make install WORKDIR /opt/tesseract RUN ./autogen.sh \ && ./configure \ && make \ && make install \ && ldconfig \ && make training \ && make training-installDockerfileのビルドdocker build --rm -f "tesseract/Dockerfile" -t tesseract:compiling "tesseract"ビルドが完了したらコンテナを立ち上げます。
tesseract 4.1.1-rc2-22-g08899
がインストールされていることが確認できます。tesseractのコンテナoot@76fa9e82e37d:/opt# tesseract -v tesseract 4.1.1-rc2-22-g08899 leptonica-1.79.0 libpng 1.6.34 : zlib 1.2.11 Found AVX2 Found AVX Found FMA Found SSE root@76fa9e82e37d:/opt#
3. まとめ
Dockerを使用することで、簡単にTesseractの環境が手に入りました。
モデルのトレーニング方法なども追加で書く予定です。
ありがとうございました。
- 投稿日:2020-01-19T14:11:56+09:00
[Docker入門]コンテナにsshでアクセスするための設定メモ
- 目的
- やりたいこと
- この記事でわかること
- 環境
- Dockerfile ※すみません、上手く記事内にリンクできませんでした。
- まとめ
- 参考
- 補足:シェルスクリプトでsshdを起動する方法
[目的]
Dockerの使い方を勉強していて、sshで接続するところで苦労したので、やり方をメモっておきます。初心者が試行錯誤した結果なので、もっと良い方法があると思います。もしご存知でしたら教えていただけますと幸いです。
[やりたいこと]
以下やりたいことです。
- 公式のubuntu18.04のイメージを使って、sshが設定済みのイメージを作成したい。
- sshでのアクセスでは公開鍵認証を使用したい。
- 必要な設定はビルド時、つまりDockerfileで完了させたい。
- コンテナを起動したら直ぐに、sshコマンドでホスト側からアクセスできる状態にしたい。
以下やりたく無いことです。
- コンテナにアクセスして、手動で直接設定を修正することはやりたくない。
[この記事でわかること]
ビルド時にsshの設定を完了させて、コンテナを起動した時点でホスト側から公開鍵を使ってsshでアクセスできるようにする方法がわかります。
[環境]
[ホスト側]
- MacOS Mojave
- Docker Desktop Community 2.1.0.5
[コンテナ側]
- ubuntu18.04
[Dockerfile]
作成したDockerfileです。公開鍵(id_rsa.pub)をイメージにコピーしていますが、id_rsa.pubの配置場所は、Dockerfileがあるフォルダ下作成したconfigフォルダです。
Dockerfile# どのイメージを基にするか FROM ubuntu:18.04 # 作成したユーザの情報 LABEL maintainter="kuboshu83" # sshサーバをインストールします RUN apt-get update && apt-get install -y openssh-server # これが無いとsshdが起動しないっぽい RUN mkdir /var/run/sshd # rootのパスワードをrootpasswdに設定します。ただし、公開鍵認証でのアクセスなので使用しませんが。。 RUN echo 'root:rootpassws' | chpasswd # sshのrootでのアクセスを許可します。ただし、パスワードでのアクセスは無効 RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config # sshのポートを22 => 20022に変更します RUN sed -i 's/#Port 22/Port 20022/' /etc/ssh/sshd_config # ホスト側にある公開鍵をイメージ側に登録します COPY ./config_files/id_rsa.pub /root/.ssh/authorized_keys EXPOSE 20022 CMD ["/usr/sbin/sshd", "-D"][接続方法]
<イメージのビルド>
以下のコマンドでビルドします。今回はイメージの名前とタグをそれぞれdefault_repoとdefault_tagにしています。
docker build -t default_repo:default_tag .<コンテナの起動>
以下のコマンドで作成したイメージからコンテナを起動します。
docker run -itd -p 20021:20022 default_repo:default_tag<ホスト側からコンテナに接続>
ホスト側からは以下のコマンドで接続できます。ホスト(localhost)の20021ポートに接続すると、コンテナ側の20022ポートに
転送されます。ssh root@localhost -p 20021
[まとめ]
ubuntu18.04を基にsshでアクセスできるイメージをビルドし、ホスト側からsshでアクセスできるようになりました。
[参考]
Dockerドキュメント:sshdデーモン用サービスのDocker化
[補足]
色々試している中で、上以外の方法でも起動できたので一応メモっておきます。ざっくりいうと、sshdの起動をDockerfileで行わず、sshdの再起動用のシェルスクリプト(setup.sh)を作成して、コンテナ起動時に.bashrcで実行するというものです。この方法だと、setup.shに書き込む内容によって、色々設定が可能なので個人的には便利だと思っています。このような方法をやって良いか悪いかは今の僕の知識では判断できませんが(^^;
<作成したファイル>
この方法では、Dockerfileとsshd再起動用のシェルスクリプト(setup.sh)を作成します。
Dockerfile
Dockerfile# どのイメージを基にするか FROM ubuntu:18.04 # 作成したユーザの情報 LABEL maintainter="kuboshu83" # RUN: docker buildする時に実行される RUN apt-get update && \ apt-get install -y --no-install-recommends openssh-server # ビルド時にsshd_configを修正 RUN sed -i 's/#PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config RUN sed -i 's/#Port 22/Port 20022/' /etc/ssh/sshd_config # ビルド時に公開鍵を登録 COPY ./config_files/id_rsa.pub /root/.ssh/authorized_keys # コンテナの起動時にsshdを再起動するようにする COPY ./config_files/setup.sh /root/ RUN chmod a+x /root/setup.sh RUN echo "/root/setup.sh" >> /root/.bashrcsetup.sh
setup.shの配置場所は、Dockerfileを配置したディレクトリ下に作成したconfigファイルです。
./config/setup.sh#!/bin/bash echo "restart ssh service" service ssh restart<接続方法>
接続方法は先ほどと同じです。
- 投稿日:2020-01-19T13:55:03+09:00
k8s環境ハンズオン webアプリケーション構築実践編
k8s環境ハンズオン webアプリケーション構築実践編
本セクションではminikubeの中に三層アプリを構築してきます。
- デバッグ用イメージ作成
- DBサーバーのイメージ作成
- DBサーバーの構築(ストレージ)
- DBサーバーの構築(Pod)
- DBサーバーの構築(Pod+Secret)
- DBサーバーの構築(StatefulSet)
- DBサーバーの構築(HeadlessService)
- DBサーバーの構築(初期化)
- APサーバーのイメージ作成
- APサーバーの構築(Pod+Secret)
- APサーバーの構築(Deployment)
- APサーバーの構築(Service)
- WEBサーバーのイメージ作成
- WEBサーバーの構築(Pod)
- WEBサーバーの構築(Pod+ConfigMap)
- WEBサーバーの構築(Deployment)
- WEBサーバーの構築(Service)
- Webアプリケーションの公開(Ingress)
作成するアプリ
minikubeの中に三層アプリを構築
web→ap→db→localstorage
デバッグ用イメージ作成
実装
1. 以下の3ファイルを作成
mongodb-org-4.0.repo
Dockerfile
debug-pod.yml確認
Docker
1. Dockerで作成したイメージを実行
2. 実行中コンテナに入る
3. 必要なコマンドが実行可能なことを確認Kubernetes
1. Podを作成mongodb-org-4.0.repo[mongodb-org-4.0] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-4.0.ascFROM centos:7 COPY . /tmp/debug RUN \ # Install MongoDB shell, tools. mv /tmp/debug/mongodb-org-4.0.repo /etc/yum.repos.d; \ yum install -y mongodb-org-shell-4.0.5 mongodb-org-tools-4.0.5; \ # Install ip , ifconfig command. yum install -y iproute net-tools; \ # Install jq curl -o /usr/local/bin/jq -L https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64; \ chmod +x /usr/local/bin/jq; \ # Delete cache files. yum clean all;debug-pod.ymlapiVersion: v1 kind: Pod metadata: name: debug namespace: default spec: containers: - name: debug image: debug imagePullPolicy: Never command: - "sh" - "-c" args: - | while true do sleep 5 done上記3ファイルをvmにうつし、ビルドコマンド実行
(dockerfileにビルド申請を投げかける)docker build -t debug .debugイメージの確認
docker image lsdebugイメージを実行する
docker run -it debug sh入り込んだコンテナで下記のコマンドでipを確認
ip;mongo;ifconfig;mongodbが正しく動いている確認したら
コンテナを削除する。docker container prune続いてk8sで動作させるマニフェストファイルapplyする
kubectl apply -f debug-pod.yml #動作確認 kubectl get pod中に入って動作確認する
kubectl exec -it debug ship;mongo;ifconfig; exit;#動作確認 kubectl get pod
DBサーバーのイメージ作成
実装
1. 以下の3ファイルを作成
.dockerignore
docker-entrypoint.sh
Dockerfile確認
1. Dockerで作成したイメージを実行
2. 実行中コンテナに入る
3. MongoDBに接続できることを確認**/.git **/.DS_Store **/node_modules#! /bin/sh INIT_FLAG_FILE=/data/db/init-completed INIT_LOG_FILE=/data/db/init-mongod.log start_mongod_as_daemon() { echo echo "> start mongod ..." echo mongod \ --fork \ --logpath ${INIT_LOG_FILE} \ --quiet \ --bind_ip 127.0.0.1 \ --smallfiles; } create_user() { echo echo "> create user ..." echo if [ ! "$MONGO_INITDB_ROOT_USERNAME" ] || [ ! "$MONGO_INITDB_ROOT_PASSWORD" ]; then return fi mongo "${MONGO_INITDB_DATABASE}" <<-EOS db.createUser({ user: "${MONGO_INITDB_ROOT_USERNAME}", pwd: "${MONGO_INITDB_ROOT_PASSWORD}", roles: [{ role: "root", db: "${MONGO_INITDB_DATABASE:-admin}"}] }) EOS } create_initialize_flag() { echo echo "> create initialize flag file ..." echo cat <<-EOF > "${INIT_FLAG_FILE}" [$(date +%Y-%m-%dT%H:%M:%S.%3N)] Initialize scripts if finigshed. EOF } stop_mongod() { echo echo "> stop mongod ..." echo mongod --shutdown } if [ ! -e ${INIT_LOG_FILE} ]; then echo echo "--- Initialize MongoDB ---" echo start_mongod_as_daemon create_user create_initialize_flag stop_mongod fi exec "$@"FROM alpine:3.9 COPY docker-entrypoint.sh /usr/local/bin RUN \ adduser -g mongodb -DH -u 1000 mongodb; \ apk --no-cache add mongodb=4.0.5-r0; \ chmod +x /usr/local/bin/docker-entrypoint.sh; \ mkdir -p /data/db; \ chown -R mongodb:mongodb /data/db; VOLUME /data/db EXPOSE 27017 ENTRYPOINT [ "docker-entrypoint.sh" ] CMD [ "mongod" ]セットしたdockerfileをビルドする。
docker build -t weblog-db:v1.0.0 .dockerをデーモン起動する。
docker run -d weblog-db:v1.0.0起動しているかコンテナ一覧確認
[root@localhost ~]# docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 46aa0fa9b017 2d3813851e87 "kube-scheduler --bi…" About a minute ago Up About a minute k8s_kube-scheduler_kube-scheduler-minikube_kube-system_31d9ee8b7fb12e797dc981a8686f6b2b_6 88649a10f187 weblog-db:v1.0.0 "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 27017/tcp gifted_spenceコンテナの中に入ってmongodbが動作しているか確認
docker exec -it gifted_spence shmongodbが正しく動いている確認
show dbsdockerコンテナ停止して削除
[root@localhost ~]# docker stop gifted_spence gifted_spence [root@localhost ~]# docker system prune
DBサーバーの構築(ストレージ)
実装
1. 以下のファイルを作成
weblog-db-storage.yml確認
※必要なフォルダが作成されていること
- PersistentVolume、PersistentVolumeClaimを作成
- 作成したリソースを確認
weblog-db-storage.ymlapiVersion: v1 kind: PersistentVolume metadata: name: storage-volume namespace: default labels: app: weblog type: storage spec: storageClassName: slow capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/data/storage" type: Directory --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: storage-claim namespace: default labels: app: weblog type: storage spec: storageClassName: slow accessModes: - ReadWriteMany resources: requests: storage: 1Gi
DBサーバーの構築(Pod)
実装
1. 以下のファイルを作成
weblog-db-pod.yml確認
※必要なフォルダが作成されていること
※作成されたフォルダは空であること
- PersistentVolume, PersistentVolumeClaim, Podを作成
- MongoDBのファイルが作成されていることを確認
- 作成したPodへ入る
- MongoDBへ接続確認
weblog-db-pod.ymlapiVersion: v1 kind: PersistentVolume metadata: name: storage-volume namespace: default labels: app: weblog type: storage spec: storageClassName: slow capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/data/storage" type: Directory --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: storage-claim labels: app: weblog type: storage spec: storageClassName: slow accessModes: - ReadWriteMany resources: requests: storage: 1Gi --- apiVersion: v1 kind: Pod metadata: name: mongodb namespace: default labels: app: weblog type: database spec: containers: - name: mongodb image: weblog-db:v1.0.0 imagePullPolicy: Never command: - "mongod" - "--bind_ip_all" volumeMounts: - mountPath: /data/db name: storage volumes: - name: storage persistentVolumeClaim: claimName: storage-claim
DBサーバーの構築(Pod+Secret)
実装
1. keyfile(ランダム文字列)を作成
2. Secretリソースを作成
3. SecretリソースのYAMLを取得
4. weblog-db-pod.ymlへマージ
5. Secretリソースを削除確認
※必要なフォルダが作成されていること
※作成されたフォルダは空であること
- PersistentVolume, Pod, Secretを作成
- 作成したPodへ入る
- MongoDBへ接続
- 設定したユーザー名/パスワードで認証
- DB一覧を表示
DFCytNO0mwawyBs25EOwptvC1TicPzI39KkojjhfE7HeR/VvryeNwqdOvOwiZ9jP/pIWIeYUYiktZXfXhOOlyMBEwUCGr+umbmEeududNy4hQCsVe0YOSlX07Xqa//o+mz4Z8pEchN0wUahqpHD5ieFyoMNIVaEcFPF43+3vZovw7M4xaY+xhhnW5etgm/c2g9GaGlJ4aXPXJbHQTylscnivBrmWiIY+JAPc+oFGJL5I3OCiSR1d66gG99ysof76Rtx0MvYgWdX9rSe16odaI3IWtmhI2CLbWpS994nYcWTCbtor3fMC1cs8nNRWy1un+JbbPooMqiRObxRncHap2X+pOKtjYPg+YKX1Htf+XyaH7DrFdZMnsVbAtAgV6Cf67IZym65p8LjjFkhZTbn5ZMgjQinwerkB+QC5hmaQQhAu6z5te+kPrsQg4PQ/JCRL7vweZEzddwlCo8NYGUJXaSG0Lg2k7wDx9oHLTuA/Telit2VrfgRbU6Y6f6FEOczjKnHKgHT09RJa56wdihgHreyWbVCC7BfdFJ2zRj1fG5YEgpkA3pgMsuvUDi6Ai6tNVe3O3jAqCmXghpFbryi9XYgtDsQkpGPRUZyLvNBj5k8qBoiYkiHPWvyIbyB9SX0pcyP10R8zR0TB8pXUZb3Xh1p4VDMTtg5u8Wwf56pIrWe3KYj20P2wWyQ3glDo5GMJxUdoubTxOun2+V0J6Oc0dKlmweqEjAbakJiDdyvty2OggnbgRSNYZInNKVR9nbnPUE/kCSMbNeE5hVVFC0zx6FKHkdxiZFEv8bP/LR4hY49OEZa9vuPRBn2LqflucO7wm5OnD8mN3PY8LlpN6SWCUTGJ2qfwm36vjRKpHxnFH6IcyDVwmbPulCMEnfnL5rKJ/4bZGiE1SQobQGYD/Gbq1UFWok0FMfTFV1wetQfVv32SISJ6PUJM2iThBJWDPNVTmKf28Dlq2NaLFMd1ugKxAWP2fN9YOgw6ZuiiRB/6UbIM7Ms2FWfytGp2oYcy94XPweblog-db-pod+secret.ymlapiVersion: v1 kind: PersistentVolume metadata: name: storage-volume namespace: default labels: app: weblog type: storage spec: storageClassName: slow capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/data/storage" type: Directory --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: storage-claim labels: app: weblog type: storage spec: storageClassName: slow accessModes: - ReadWriteMany resources: requests: storage: 1Gi --- apiVersion: v1 kind: Secret metadata: name: mongo-secret namespace: default labels: app: weblog type: database type: Opaque data: root_username: YWRtaW4= root_password: UGFzc3cwcmQ= keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo= --- apiVersion: v1 kind: Pod metadata: name: mongodb namespace: default labels: app: weblog type: database spec: containers: - name: mongodb image: weblog-db:v1.0.0 imagePullPolicy: Never args: - "mongod" - "--auth" - "--bind_ip_all" env: - name: "MONGO_INITDB_ROOT_USERNAME" valueFrom: secretKeyRef: name: mongo-secret key: root_username - name: "MONGO_INITDB_ROOT_PASSWORD" valueFrom: secretKeyRef: name: mongo-secret key: root_password - name: "MONGO_INITDB_DATABASE" value: "admin" volumeMounts: - mountPath: /data/db name: storage - mountPath: /home/mongodb name: secret volumes: - name: storage persistentVolumeClaim: claimName: storage-claim - name: secret secret: secretName: mongo-secret items: - key: keyfile path: keyfile mode: 0700
DBサーバーの構築(StatefulSet)
実装
1. 以下のファイルを作成
weblog-db-statefulset.yml確認
※必要なフォルダが作成されていること
※作成されたフォルダは空であること
- PersistentVolume, Secret, StatefulSetを作成
- 作成したPodへ入る
- MongoDBへ接続
- 設定したユーザー名/パスワードで認証
- DB一覧を表示
weblog-db-statefulset.ymlapiVersion: v1 kind: PersistentVolume metadata: name: storage-volume-0 namespace: default labels: app: weblog type: storage spec: storageClassName: slow capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/data/pv0000" type: Directory --- apiVersion: v1 kind: PersistentVolume metadata: name: storage-volume-1 namespace: default labels: app: weblog type: storage spec: storageClassName: slow capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/data/pv0001" type: Directory --- apiVersion: v1 kind: PersistentVolume metadata: name: storage-volume-2 namespace: default labels: app: weblog type: storage spec: storageClassName: slow capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/data/pv0002" type: Directory --- apiVersion: v1 kind: Secret metadata: name: mongo-secret namespace: default labels: app: weblog type: database type: Opaque data: root_username: YWRtaW4= root_password: UGFzc3cwcmQ= keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo= --- apiVersion: apps/v1 kind: StatefulSet metadata: name: mongo namespace: default labels: app: weblog type: database spec: selector: matchLabels: app: weblog type: database serviceName: db-svc replicas: 3 template: metadata: name: mongodb namespace: default labels: app: weblog type: database spec: terminationGracePeriodSeconds: 10 containers: - name: mongodb image: weblog-db:v1.0.0 imagePullPolicy: Never args: - "mongod" - "--auth" - "--clusterAuthMode=keyFile" - "--keyFile=/home/mongodb/keyfile" - "--replSet=rs0" - "--bind_ip_all" env: - name: "MONGO_INITDB_ROOT_USERNAME" valueFrom: secretKeyRef: name: mongo-secret key: root_username - name: "MONGO_INITDB_ROOT_PASSWORD" valueFrom: secretKeyRef: name: mongo-secret key: root_password - name: "MONGO_INITDB_DATABASE" value: "admin" volumeMounts: - mountPath: /data/db name: storage - mountPath: /home/mongodb name: secret volumes: - name: secret secret: secretName: mongo-secret items: - key: keyfile path: keyfile mode: 0700 volumeClaimTemplates: - metadata: name: storage spec: storageClassName: slow accessModes: - ReadWriteMany resources: requests: storage: 1Gi
DBサーバーの構築(HeadlessService)
実装
1. 以下のファイルを作成
weblog-db-fullset.yml確認
※必要なフォルダが作成されていること
※作成されたフォルダは空であること
- PersistentVolume, Secret, StatefulSet, Serviceを作成
- 作成したPodへ入る
- MongoDBを初期化
- レプリカセット構築できていることを確認
weblog-db-fullset.ymlapiVersion: v1 kind: PersistentVolume metadata: name: storage-volume-0 namespace: default labels: app: weblog type: storage spec: storageClassName: slow capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/data/pv0000" type: Directory --- apiVersion: v1 kind: PersistentVolume metadata: name: storage-volume-1 namespace: default labels: app: weblog type: storage spec: storageClassName: slow capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/data/pv0001" type: Directory --- apiVersion: v1 kind: PersistentVolume metadata: name: storage-volume-2 namespace: default labels: app: weblog type: storage spec: storageClassName: slow capacity: storage: 1Gi accessModes: - ReadWriteMany hostPath: path: "/data/pv0002" type: Directory --- apiVersion: v1 kind: Secret metadata: name: mongo-secret namespace: default labels: app: weblog type: database type: Opaque data: root_username: YWRtaW4= root_password: UGFzc3cwcmQ= keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo= --- apiVersion: v1 kind: Service metadata: name: db-svc namespace: default labels: app: weblog type: database spec: ports: - port: 27017 targetPort: 27017 clusterIP: None selector: app: weblog type: database --- apiVersion: apps/v1 kind: StatefulSet metadata: name: mongo namespace: default labels: app: weblog type: database spec: selector: matchLabels: app: weblog type: database serviceName: db-svc replicas: 3 template: metadata: name: mongodb namespace: default labels: app: weblog type: database spec: terminationGracePeriodSeconds: 10 containers: - name: mongodb image: weblog-db:v1.0.0 imagePullPolicy: Never args: - "mongod" - "--auth" - "--clusterAuthMode=keyFile" - "--keyFile=/home/mongodb/keyfile" - "--replSet=rs0" - "--bind_ip_all" env: - name: "MONGO_INITDB_ROOT_USERNAME" valueFrom: secretKeyRef: name: mongo-secret key: root_username - name: "MONGO_INITDB_ROOT_PASSWORD" valueFrom: secretKeyRef: name: mongo-secret key: root_password - name: "MONGO_INITDB_DATABASE" value: "admin" volumeMounts: - mountPath: /data/db name: storage - mountPath: /home/mongodb name: secret volumes: - name: secret secret: secretName: mongo-secret items: - key: keyfile path: keyfile mode: 0700 volumeClaimTemplates: - metadata: name: storage spec: storageClassName: slow accessModes: - ReadWriteMany resources: requests: storage: 1Gi
DBサーバーの構築(初期化)
- デバッグ用Podを起動
- 初期化スクリプトをデバッグ用Podへコピー
- デバッグ用Podへ入る
- MongoDBへ接続してプライマリを確認して切断
- 初期化スクリプトを修正(必要であれば)
- 初期化スクリプトを実行
- いずれかのMongoDBに接続してデータが入ったことを確認
adduser.js// use weblog db.createUser({ user: "user", pwd: "welcome", roles: [{ role: "readWrite", db: "weblog" }] })drop.jsdb.posts.drop(); db.users.drop(); db.privileges.drop();init.sh# Create user mongo mongodb://mongo-0.db-svc:27017/weblog -u admin -p Passw0rd --authenticationDatabase admin ./adduser.js # Create collection & insert initial data mongo mongodb://mongo-0.db-svc:27017/weblog -u admin -p Passw0rd --authenticationDatabase admin ./insert.jsinsert.js// // posts table // db.posts.createIndex({ url: 1 }, { unique: true, background: true }); db.posts.insertMany([{ url: "/2017/05/hello-nodejs.html", published: new Date(2017, 4, 2), updated: new Date(2017, 4, 2), title: "ようこそ Node.js の世界へ", content: "Node.js は おもしろい!", keywords: ["Node.js"], authors: ["Yuta Sato"] }, { url: "/2017/06/nodejs-basic.html", published: new Date(2017, 5, 12), updated: new Date(2017, 5, 12), title: "Node.js の 基本", content: "ちょっと難しくなってきた!?", keywords: ["Node.js"], authors: ["Yuta Sato"] }, { url: "/2017/07/advanced-nodejs.html", published: new Date(2017, 7, 8), updated: new Date(2017, 7, 8), title: "Node.js 応用", content: "Node.js で Excel ファイルが触れるなんて!!", keywords: ["Node.js"], authors: ["Yuta Sato"] }]); // // users table // db.users.createIndex({ email: 1 }, { unique: true, background: true }); db.users.insertMany([{ email: "yuta.sato@sample.com", name: "Yuta Sato", password: "77d1fb804f4e1e6059377122046c95de5e567cb9fd374639cb96e7f5cc07dba1", //"qwerty", // "77d1fb804f4e1e6059377122046c95de5e567cb9fd374639cb96e7f5cc07dba1" role: "owner" }]); // // privileges table // db.privileges.createIndex({ role: 1 }, { unique: true, background: true }); db.privileges.insertMany([ { role: "default", permissions: ["read"] }, { role: "owner", permissions: ["readWrite"] } ]);
APサーバーのイメージ作成
実装
1. 以下のファイルを作成ROOT │ │ .dockerignore │ docker-entrypoint.sh │ Dockerfile │ │ --- 以下は Node.js アプリ Application フォルダに配置--- │ app.js │ package.json │ yarn.lock │ ├─ api ├─ config ├─ lib ├─ log ├─ public ├─ routes └─ views確認
※DBサーバーが起動して初期化まで済んでいること
- MongoDBのプライマリを確認
- MongoDBに対するService, Endpointsを作成(kubectl apply)
- Dockerで作成したイメージを実行(docker run)
- 作成したNode.jsアプリケーションコンテナへ接続(curl)
- MongoDB接続用Service, Endpointsを削除(kubectl delete)
APサーバーの構築(Pod+Secret)
実装
1. 以下のファイルを作成
weblog-app-pod.yml確認
※DBサーバーが起動して初期化まで済んでいること
- Secret, Podを作成(kubectl apply)
- デバッグPodを作成して入る(kubectl exec)
- APサーバーPodへ接続確認(curl)
weblog-app-pod.ymlapiVersion: v1 kind: Secret metadata: name: mongo-secret namespace: default labels: app: weblog type: database type: Opaque data: root_username: YWRtaW4= root_password: UGFzc3cwcmQ= weblog_username: dXNlcg== # user weblog_password: d2VsY29tZQ== # welcome keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo= --- apiVersion: v1 kind: Pod metadata: name: nodeapp namespace: default labels: app: weblog type: application spec: containers: - name: node image: weblog-app:v1.0.0 imagePullPolicy: Never ports: - containerPort: 3000 env: - name: "MONGODB_USERNAME" valueFrom: secretKeyRef: name: mongo-secret key: weblog_username - name: "MONGODB_PASSWORD" valueFrom: secretKeyRef: name: mongo-secret key: weblog_password - name: "MONGODB_HOSTS" value: "mongo-0.db-svc:27017,mongo-1.db-svc:27017,mongo-2.db-svc:27017," - name: "MONGODB_DATABASE" value: "weblog" - name: "MONGODB_REPLICASET" value: "rs0"
APサーバーの構築(Deployment)
実装
1. 以下のファイルを作成
weblog-app-deployment.yml確認
※DBサーバーが起動して初期化まで済んでいること
- Secret, Deploymentを作成(kubectl apply)
- デバッグPodを作成して入る(kubectl exec)
- APサーバーPodへ接続確認(curl)
weblog-app-deployment.ymlapiVersion: v1 kind: Secret metadata: name: mongo-secret namespace: default labels: app: weblog type: database type: Opaque data: root_username: YWRtaW4= root_password: UGFzc3cwcmQ= weblog_username: dXNlcg== # user weblog_password: d2VsY29tZQ== # welcome keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo= --- apiVersion: apps/v1 kind: Deployment metadata: name: nodeapp namespace: default labels: app: weblog type: application spec: replicas: 3 selector: matchLabels: app: weblog type: application strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate revisionHistoryLimit: 14 template: metadata: name: nodeapp namespace: default labels: app: weblog type: application spec: containers: - name: node image: weblog-app:v1.0.0 imagePullPolicy: Never ports: - containerPort: 3000 env: - name: "MONGODB_USERNAME" valueFrom: secretKeyRef: name: mongo-secret key: weblog_username - name: "MONGODB_PASSWORD" valueFrom: secretKeyRef: name: mongo-secret key: weblog_password - name: "MONGODB_HOSTS" value: "mongo-0.db-svc:27017,mongo-1.db-svc:27017,mongo-2.db-svc:27017," - name: "MONGODB_DATABASE" value: "weblog" - name: "MONGODB_REPLICASET" value: "rs0"
APサーバーの構築(Service)
実装
1. 以下のファイルを作成
weblog-app-fullset.yml確認
※DBサーバーが起動して初期化まで済んでいること
- Secret, Deployment, Serviceを作成(kubectl apply)
- デバッグPodを作成して入る(kubectl exec)
- APサーバーへService経由で接続(curl)
- APサーバーのいずれかにログ出力されていることを確認
weblog-app-fullset.ymlapiVersion: v1 kind: Secret metadata: name: mongo-secret namespace: default labels: app: weblog type: database type: Opaque data: root_username: YWRtaW4= root_password: UGFzc3cwcmQ= weblog_username: dXNlcg== # user weblog_password: d2VsY29tZQ== # welcome keyfile: REZDeXROTzBtd2F3eUJzMjVFT3dwdHZDMVRpY1B6STM5S2tvampoZkU3SGVSL1Z2cnllTndxZE92T3dpWjlqUC9wSVdJZVlVWWlrdFpYZlhoT09seU1CRXdVQ0dyK3VtYm1FZXVkdWROeTRoUUNzVmUwWU9TbFgwN1hxYS8vbyttejRaOHBFY2hOMHdVYWhxcEhENWllRnlvTU5JVmFFY0ZQRjQzKzN2Wm92dzdNNHhhWSt4aGhuVzVldGdtL2MyZzlHYUdsSjRhWFBYSmJIUVR5bHNjbml2QnJtV2lJWStKQVBjK29GR0pMNUkzT0NpU1IxZDY2Z0c5OXlzb2Y3NlJ0eDBNdllnV2RYOXJTZTE2b2RhSTNJV3RtaEkyQ0xiV3BTOTk0blljV1RDYnRvcjNmTUMxY3M4bk5SV3kxdW4rSmJiUG9vTXFpUk9ieFJuY0hhcDJYK3BPS3RqWVBnK1lLWDFIdGYrWHlhSDdEckZkWk1uc1ZiQXRBZ1Y2Q2Y2N0laeW02NXA4TGpqRmtoWlRibjVaTWdqUWlud2Vya0IrUUM1aG1hUVFoQXU2ejV0ZStrUHJzUWc0UFEvSkNSTDd2d2VaRXpkZHdsQ284TllHVUpYYVNHMExnMms3d0R4OW9ITFR1QS9UZWxpdDJWcmZnUmJVNlk2ZjZGRU9jempLbkhLZ0hUMDlSSmE1NndkaWhnSHJleVdiVkNDN0JmZEZKMnpSajFmRzVZRWdwa0EzcGdNc3V2VURpNkFpNnROVmUzTzNqQXFDbVhnaHBGYnJ5aTlYWWd0RHNRa3BHUFJVWnlMdk5CajVrOHFCb2lZa2lIUFd2eUlieUI5U1gwcGN5UDEwUjh6UjBUQjhwWFVaYjNYaDFwNFZETVR0ZzV1OFd3ZjU2cElyV2UzS1lqMjBQMndXeVEzZ2xEbzVHTUp4VWRvdWJUeE91bjIrVjBKNk9jMGRLbG13ZXFFakFiYWtKaURkeXZ0eTJPZ2duYmdSU05ZWkluTktWUjluYm5QVUUva0NTTWJOZUU1aFZWRkMweng2RktIa2R4aVpGRXY4YlAvTFI0aFk0OU9FWmE5dnVQUkJuMkxxZmx1Y083d201T25EOG1OM1BZOExscE42U1dDVVRHSjJxZndtMzZ2alJLcEh4bkZINkljeURWd21iUHVsQ01FbmZuTDVyS0ovNGJaR2lFMVNRb2JRR1lEL0dicTFVRldvazBGTWZURlYxd2V0UWZWdjMyU0lTSjZQVUpNMmlUaEJKV0RQTlZUbUtmMjhEbHEyTmFMRk1kMXVnS3hBV1AyZk45WU9ndzZadWlpUkIvNlViSU03TXMyRldmeXRHcDJvWWN5OTRYUAo= --- apiVersion: v1 kind: Service metadata: name: app-svc namespace: default labels: app: weblog type: application spec: ports: - port: 3000 targetPort: 3000 selector: app: weblog type: application --- apiVersion: apps/v1 kind: Deployment metadata: name: nodeapp namespace: default labels: app: weblog type: application spec: replicas: 3 selector: matchLabels: app: weblog type: application strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate revisionHistoryLimit: 14 template: metadata: name: nodeapp namespace: default labels: app: weblog type: application spec: containers: - name: node image: weblog-app:v1.0.0 imagePullPolicy: Never ports: - containerPort: 3000 env: - name: "MONGODB_USERNAME" valueFrom: secretKeyRef: name: mongo-secret key: weblog_username - name: "MONGODB_PASSWORD" valueFrom: secretKeyRef: name: mongo-secret key: weblog_password - name: "MONGODB_HOSTS" value: "mongo-0.db-svc:27017,mongo-1.db-svc:27017,mongo-2.db-svc:27017," - name: "MONGODB_DATABASE" value: "weblog" - name: "MONGODB_REPLICASET" value: "rs0"
WEBサーバーのイメージ作成
実装
1. 以下のファイルを作成
ROOT
docker-entrypoint.sh
Dockerfile※nginx.confは添付を利用
確認
※Kubernetes上でDBサーバーとAPサーバーが起動していること
- APサーバーへアクセスするServiceを作成
- Webサーバーコンテナ起動
- 外部からブラウザでアクセスして画面確認
nginx.confuser nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server_tokens off; proxy_cache_path /var/cache/nginx keys_zone=STATIC:10m max_size=1g inactive=10d; proxy_temp_path /var/cache/nginx/tmp; server { listen 80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://${APPLICATION_HOST}/; } location /public/ { proxy_pass http://${APPLICATION_HOST}/public/; proxy_ignore_headers Cache-Control Expires; proxy_buffering on; proxy_cache STATIC; proxy_cache_valid any 10d; add_header X-Nginx-Cache $upstream_cache_status; } } # include /etc/nginx/conf.d/*.conf; }docker-entrypoint.sh#! /bin/sh envsubst '$$APPLICATION_HOST' \ < /home/nginx/nginx.conf \ > /etc/nginx/nginx.conf exec "$@"FROM nginx:1.17.2-alpine COPY . /home/nginx RUN cd /home/nginx; \ mv docker-entrypoint.sh /usr/local/bin; \ chmod +x /usr/local/bin/docker-entrypoint.sh; ENTRYPOINT ["docker-entrypoint.sh"] CMD ["nginx", "-g", "daemon off;"] weblog-app-service.yml apiVersion: v1 kind: Service metadata: name: nodeapp namespace: default labels: env: study spec: type: NodePort selector: app: weblog type: application ports: - port: 3000 targetPort: 3000 nodePort: 30000
WEBサーバーの構築(Pod)
実装
1. 以下のファイルを作成
weblog-web-pod.yml確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること
- ConfigMap, Deployment, Serviceを作成(kubectl apply)
- 作成したWebサーバーPodのIPアドレスを確認(kubectl get)
- デバッグPodを作成して入る(kubectl exec)
- Webサーバーへ接続(curl)
- 接続したWebサーバーにアクセスログがあることを確認
weblog-web-pod.ymlapiVersion: v1 kind: Pod metadata: name: nginx namespace: default labels: app: weblog type: frontend spec: containers: - name: nginx image: weblog-web:v1.0.0 imagePullPolicy: Never ports: - containerPort: 80 env: - name: "APPLICATION_HOST" value: "app-svc:3000"
WEBサーバーの構築(Pod+ConfigMap)
実装
1. 以下のファイルを作成
weblog-web-pod+configmap.yml確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること
- ConfigMap, Podを作成(kubectl apply)
- WebサーバーPodに入ってConfigMapを利用していることを確認(kubectl exec)
- WebサーバーPodのIPアドレスを確認(kubectl get)
- デバッグPodを作成して入る(kubectl exec)
- WebサーバーPodへ接続確認(curl)
weblog-web-pod+configmap.ymlapiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: default labels: app: weblog type: frontend data: nginx.conf: | user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server_tokens off; proxy_cache_path /var/cache/nginx keys_zone=STATIC:10m max_size=1g inactive=10d; proxy_temp_path /var/cache/nginx/tmp; server { listen 80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://${APPLICATION_HOST}/; } location /public/ { proxy_pass http://${APPLICATION_HOST}/public/; proxy_ignore_headers Cache-Control Expires; proxy_buffering on; proxy_cache STATIC; proxy_cache_valid any 10d; add_header X-Nginx-Cache $upstream_cache_status; } } # include /etc/nginx/conf.d/*.conf; # ConfigMap } --- apiVersion: v1 kind: Pod metadata: name: nginx namespace: default labels: app: weblog type: frontend spec: containers: - name: nginx image: weblog-web:v1.0.0 imagePullPolicy: Never ports: - containerPort: 80 env: - name: "APPLICATION_HOST" value: "app-svc:3000" volumeMounts: - name: config-volume mountPath: /home/nginx volumes: - name: config-volume configMap: name: nginx-config
WEBサーバーの構築(Deployment)
実装
1. 以下のファイルを作成
weblog-web-deployment.yml確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること
- ConfigMap, Deploymentを作成(kubectl apply)
- WebサーバーPodのIPアドレスを確認(kubectl get)
- デバッグPodを作成して入る(kubectl exec)
- WebサーバーPodいずれかへ接続確認(curl)
weblog-web-deployment.ymlapiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: default labels: app: weblog type: frontend data: nginx.conf: | user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server_tokens off; proxy_cache_path /var/cache/nginx keys_zone=STATIC:10m max_size=1g inactive=10d; proxy_temp_path /var/cache/nginx/tmp; server { listen 80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://${APPLICATION_HOST}/; } location /public/ { proxy_pass http://${APPLICATION_HOST}/public/; proxy_ignore_headers Cache-Control Expires; proxy_buffering on; proxy_cache STATIC; proxy_cache_valid any 10d; add_header X-Nginx-Cache $upstream_cache_status; } } # include /etc/nginx/conf.d/*.conf; # ConfigMap } --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx namespace: default labels: app: weblog type: frontend spec: replicas: 3 selector: matchLabels: app: weblog type: frontend strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate revisionHistoryLimit: 14 template: metadata: name: nginx namespace: default labels: app: weblog type: frontend spec: containers: - name: nginx image: weblog-web:v1.0.0 imagePullPolicy: Never ports: - containerPort: 80 env: - name: "APPLICATION_HOST" value: "app-svc:3000" volumeMounts: - name: config-volume mountPath: /home/nginx volumes: - name: config-volume configMap: name: nginx-config
WEBサーバーの構築(Service)
実装
1. 以下のファイルを作成
weblog-web-fullset.yml確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること
- ConfigMap, Deploymentを作成(kubectl apply)
- デバッグPodを作成して入る(kubectl exec)
- WebサーバーServiceへ接続確認(curl)
weblog-web-fullset.ymlapiVersion: v1 kind: Service metadata: name: web-svc namespace: default labels: app: weblog type: frontend spec: ports: - port: 80 targetPort: 80 selector: app: weblog type: frontend --- apiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: default labels: app: weblog type: frontend data: nginx.conf: | user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server_tokens off; proxy_cache_path /var/cache/nginx keys_zone=STATIC:10m max_size=1g inactive=10d; proxy_temp_path /var/cache/nginx/tmp; server { listen 80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://${APPLICATION_HOST}/; } location /public/ { proxy_pass http://${APPLICATION_HOST}/public/; proxy_ignore_headers Cache-Control Expires; proxy_buffering on; proxy_cache STATIC; proxy_cache_valid any 10d; add_header X-Nginx-Cache $upstream_cache_status; } } # include /etc/nginx/conf.d/*.conf; # ConfigMap } --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx namespace: default labels: app: weblog type: frontend spec: replicas: 3 selector: matchLabels: app: weblog type: frontend strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate revisionHistoryLimit: 14 template: metadata: name: nginx namespace: default labels: app: weblog type: frontend spec: containers: - name: nginx image: weblog-web:v1.0.0 imagePullPolicy: Never ports: - containerPort: 80 env: - name: "APPLICATION_HOST" value: "app-svc:3000" volumeMounts: - name: config-volume mountPath: /home/nginx volumes: - name: config-volume configMap: name: nginx-config
Webアプリケーションの公開(Ingress)
実装
1. 以下のファイルを作成
weblog-ingress.yml確認
※DBサーバーが起動して初期化まで済んでいること
※APサーバーが起動していること
※Webサーバーが起動していること
- Ingressを作成(kubectl apply)
- minikubeへ接続確認(ブラウザ)
weblog-ingress.ymlapiVersion: extensions/v1beta1 kind: Ingress metadata: name: entrypoint namespace: default annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/ssl-redirect: "false" labels: app: weblog type: entrypoint spec: rules: - http: paths: - path: / backend: serviceName: web-svc servicePort: 80
- 投稿日:2020-01-19T13:07:53+09:00
GCP+DockerでHTTPSな静的ページを公開する
概要
なにかかっこいいのでポートフォリオサイトが欲しかったというのと,GCPとDockerまともに触ったことがなかったのでこういう風に公開しました.
これはポートフォリオに限らず,一般的な静的ページなら当てはめられます.手順
1. ドメインを取得してIPと紐づける
僕はGoogleDomainsで取得して設定しました.
2. Google Compute Engine(GCE) のインスタンスを立てる
OSはdebian9を選択する.
httpとhttpsのportを開放することを忘れずに.3. GCE 上に Docker をインストールする
$ apt-get install curl $ curl -fsSL https://get.docker.com -o get-docker.sh $ sudo sh get-docker.sh $ systemctl start docker4. GCE 上に git をインストールする
ローカルのソースコードを GCE 上にコピーします.
$ apt-get install git $ git clone https://github.com/[Your Account]/[Your Repository].gitプライベートリポジトリなら,Githubに鍵登録をしましょう.
Github以外の方法でソースコードをコピーしても問題ありません.ディレクトリ構成
. ├── Dockerfile ├── docker-compose.yml └── src ├── css ├── favicon.ico ├── img ├── index.html └── js5. GCE 上に Docker で HTTPS な Nginx を立てる
https-portal
を利用します.
https://github.com/SteveLTN/https-portalこれは普通はproxyとしてHTTPS化するものですが,今回はproxyとしてではなくhttp-portl自体のNginxから静的ファイルを配信します.
git でクローンしたディレクトリに入りイメージをビルドします.公開したいテンプレート
src
を/var/www/vhosts/www.[Your Domain].com/
に配置しコンテナにコピーします.
srcを変更した場合、変更がそのまま反映されます.
こうすることで,imageをビルドしなおすことなくページ内容の変更を反映させることができます.証明書をボリュームにマウントしておき永続化します.
コンテナを立ち上げるため証明書を取得すると発行制限がかかる場合があり,僕は1週間くらい発行することができなくなりました.$ docker build ./ -t portfolio-https $ docker run -v {srcへの絶対パス}:/var/www/vhosts/www.[Your Domain].com/ -v /data/ssl_certs:/var/lib/https-portal -p 80:80 -p 443:443 portfolio-httpsもしくは
docker-compose.ymlversion: "3" services: https-portal: image: steveltn/https-portal:1 container_name: portfolio-https-portal ports: - "80:80" - "443:443" restart: always environment: STAGE: "production" DOMAINS: >- www.[Your Domain].com volumes: - ./src:/var/www/vhosts/www.[Your Domain].com - /data/ssl_certs:/var/lib/https-portaldocker-compose up -d
まとめ
以上の手順でページを公開できたと思います.
- 投稿日:2020-01-19T12:55:53+09:00
TruffleBox (React&Truffle)を用いたDockerでのdapps(ブロックチェーンアプリ)の開発環境の構築
やったこと
- Docker上でTrufflebox(React&Truffle)を用いたdappsの開発環境を構築した。
- ホスト側のIPアドレスを設定することで、Dockerのコンテナからホストで立ち上がっているganacheに接続できるようにした。
今回の成果
環境構築手順
各種ファイルの用意
まずは、docker-compose.ymlとDockerfileを用意します。
docker-compose.yml
docker-compose.ymlversion: '3' services: truffle: build: context: ./truffle/ dockerfile: Dockerfile volumes: - ./truffle:/usr/src/app command: sh -c "cd client && yarn start" ports: - "8003:3000"DockerFile
DockerfileFROM node:8-alpine RUN apk add --update alpine-sdk RUN apk add --no-cache git python g++ make \ && npm i -g --unsafe-perm=true --allow-root truffle WORKDIR /usr/src/appコマンドの実行
$ docker-compose build $ docker-compose run truffle truffle unbox react ✔ cleaning up temporary files ✔ Setting up boxtruffle-config.jsの編集
truffle-config.jsconst path = require("path"); module.exports = { // See <http://truffleframework.com/docs/advanced/configuration> // to customize your Truffle configuration! networks: { development: { host: "10.200.10.1", port: 7545, network_id: "*" // Match any network id } }, contracts_build_directory: path.join(__dirname, "client/src/contracts") };ホストOS側でのIPアドレスの設定
ganacheを使って、ローカル開発環境上でEthereumのブロックチェーンを構築するのですが、
Mac(ホストOS)上で立ち上がってるganacheにDockerのコンテナ上のtruffleからアクセスできるようにするために、Mac側のIPアドレスを独自に設定します。MacのTerminalで$ sudo ifconfig lo0 alias 10.200.10.1/24 $ ifconfig lo0: inet 127.0.0.1 netmask 0xff000000 ... inet 10.200.10.1 netmask 0xffffff00これにより、10.200.10.1でDockerからホストOSへアクセスできるようになった。
参考記事: https://qiita.com/ynii/items/262d2344b9e1ef4d2d88netmaskとganacheの設定
参考記事に従って、設定してください。
参考記事: https://qiita.com/kane-hiro/items/b1381cc1c8dd5559a9d2ganacheの設定で、一つだけ追加の設定が必要です。
上で設定したIPアドレス:10.200.10.1でサーバーを立ててほしいので、その設定を行います。
設定 -> server -> lo0:10.200.10.1に変更
truffle-config.jsonの設定
truffleが参照するganacheサーバーの情報(IPとポート)について、記述していきます。
truffle-config.jsconst path = require("path"); module.exports = { // See <http://truffleframework.com/docs/advanced/configuration> // to customize your Truffle configuration! networks: { development: { host: "10.200.10.1", port: 7545, network_id: "*" // Match any network id } }, contracts_build_directory: path.join(__dirname, "client/src/contracts") };migrateとフロントの立ち上げ
$ docker-compose run truffle truffle migrate $ docker-compose upハマったポイント
DockerFileの記述はかなりハマりました。
npm install truffleのパーミッションエラーを回避する
$ npm i -g truffle ... EACCES: permission denied, open '/root/.config/truffle/config.json何も考えずに
npm i -g truffle
すると、エラーを吐くと思います。
これは、
- Dockerでnpm installするときは、rootでインストールを始めようとする
--unsafe-perm
オプションをtrueにしないとrootでnpm installができないようになっている?(rootでのインストールが推奨されていないから???)参考記事: https://qiita.com/village_21/items/8ed91270271261752c8a
gitとかpythonを入れましょう。
何もいれないと、
truffle unbox react
でエラーを吐きます。
- 投稿日:2020-01-19T01:19:09+09:00
Pytestの実行時にDockerコンテナを起動する
Pytestのテスト実行前にDockerコンテナを起動することを考える。
周辺ミドルウェアとのインテグレーションテストが容易に行えるようになり、環境やテストデータや冪等性を得られるメリットがある。例としてテスト実行時にPostgreSQLコンテナを起動し、データを投入してみる。
備考
コード例の前に、ユニットテストの中でDockerコンテナを使用することの制約などについて考えてみる。
Dockerデーモンが起動している必要がある
-> 当然といえば当然だが重要。コンテナの中でテスト実行したいようなケースにはハードルが1つ増える(?)
- Docker in Dockerができるコンテナをビルドすればできそう(未検証)。
- 参考: Docker in Docker のベタープラクティス
コンテナ起動まで待機する必要あり
- コンテナ自体の起動は高速だが、内部のプロセスが起動完了して使用可能になるまでは数秒かかる場合が多い。
- テスト関数が増えてくると全テストケース実行時間が大幅に増加してしまう
- なるべく軽量なコンテナイメージを使う方が良い
- コンテナの標準出力をウォッチすることで準備完了になるまで適切に待機するよう工夫する
使用ライブラリ
- pytest: ユニットテスト
- docker: Docker APIのラッパー - docker - PyPI
- SQLAlchemy: ORM
- psycopg2: PostgreSQL接続ドライバ
$ pip install docker pytest SQLAlchemy psycopg2-binary構成
├── main.py ├── models.py └── tests ├── __init__.py ├── conftest.py └── test_main.pyメイン処理/DBモデル
- models.py
models.pyfrom sqlalchemy import Column, Integer, String from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Staff(Base): __tablename__ = 'staff' id = Column(Integer, primary_key=True) name = Column(String)
- main.py
main.pyfrom sqlalchemy.orm import Session from models import Staff def add_staff(engine, name): session = Session(bind=engine) staff = Staff() staff.name = name session.add(staff) session.commit()テストコード
SQLAlchemyのengineをフィクスチャにすることでテスト関数で使用できるようにするのがポイント。
- conftest.py
tests/conftest.pyimport time import pytest import docker from sqlalchemy import create_engine @pytest.fixture() def pg_conf(): """PostgreSQLの設定を管理""" host = '127.0.0.1' port = 5432 dbname = 'pytest' user = 'testuser' password = 'test' pg_conf = {'host': host, 'port': port, 'dbname': dbname, 'user': user, 'password': password, 'url': f'postgresql://{user}:{password}@{host}/{dbname}'} return pg_conf @pytest.fixture() def engine(pg_conf): return create_engine(pg_conf['url']) @pytest.fixture(autouse=True) def pg_container(pg_conf): """PostgreSQLコンテナを起動する""" client = docker.from_env() container = client.containers.run(image='postgres:11.6-alpine', tty=True, detach=True, auto_remove=True, environment={'POSTGRES_DB': pg_conf['dbname'], 'POSTGRES_USER': pg_conf['user'], 'POSTGRES_PASSWORD': pg_conf['password']}, ports={pg_conf['port']: '5432'}) # コンテナが準備完了になるまで待機 while True: log = container.logs(tail=1) if 'database system is ready to accept connections' in log.decode(): break time.sleep(0.5) yield # ここでテストに遷移 container.kill()コンテナ内の標準出力をチェックしているが、待機間隔が短すぎる(0.4秒間隔以下)とエラーが発生してしまった。
少し猶予を持った待機時間にしたほうが良さそう。
- test_main.py
test_main.pyfrom sqlalchemy.orm import Session from models import Base, Staff from main import add_staff def test_add(engine): # レコードを1件追加 Base.metadata.create_all(bind=engine) # テーブルを作成 add_staff(engine=engine, name='alice') # 追加したレコードをチェック session = Session(bind=engine) assert session.query(Staff.id).filter_by(name='alice').first() == (1,) session.close()実行結果
$ pytest --setup-show tests/ -v -s ========================================= test session starts =========================================platform linux -- Python 3.8.1, pytest-5.3.3, py-1.8.1, pluggy-0.13.1 -- /home/skokado/.local/share/virtualenvs/sandbox-pTebjwBw/bin/python3.8 cachedir: .pytest_cache rootdir: *** collected 1 item tests/test_pg.py::test_add SETUP F pg_conf SETUP F pg_container (fixtures used: pg_conf) SETUP F engine (fixtures used: pg_conf) tests/test_main.py::test_add (fixtures used: engine, pg_conf, pg_container)PASSED TEARDOWN F engine TEARDOWN F pg_container TEARDOWN F pg_conf ========================================== 1 passed in 2.00s ==========================================
- 投稿日:2020-01-19T00:37:15+09:00
k8s環境ハンズオン k8s各種リソース解説編
k8s各種リソース解説編
本セクションでは主要なKubernetesリソースの使い方を学習していきます。
- Pod
- ReplicaSet
- Deployment
- Service
- ConfigMap
- Secret
- PersistentVolume
- PersistentVolumeClaim
- StatefulSet
- Ingress
Kubernetesを使った開発を行っていく上で基本となるリソースの使い方を学習していきます。
各リソースの特徴や記述方法について学習し、使えるようになることを目指しましょう!
Pod
podとは、最小単位。同一環境で動作するdockerコンテナ集合
1つのpodに複数のdockerコンテナが入れられる。
- マニフェストファイル書き方
pod.yamlapiVersion: v1 kind: Pod metadata: name: sample spec: containers: - name: nginx image: nginx:1.17.2-alpine volumeMounts: - name: storage mountPath: /home/nginx volumes: - name: storage hostPath: path: "/data/storage" type: DirectoryimagePullpolicyの各種オプション
種別 説明 Always 毎回リポジトリからダウンロードを行う Never ローカルのイメージを利用 ifNotpresent ローカルに存在すればローカルを利用し存在しなければリポジトリからダウンロード マニフェスト設定は下記の通り
種別 説明 spec:containers:name コンテナ名指定 spec:containers:image イメージ名指定 spec:containers:command コンテナへ引き渡すエントリポイントのコマンドを指定 spec:containers:args コンテナへ引き渡すcmdコマンドを指定 spec:containers:env コンテナへ引き渡す環境変数を指定 spec:containers:volumeMounts コンテナへマウントするストレージを指定 主要なspecは containersとvolumes
spec:volumes
マウントしたいストレージ先は状況に応じて選択spec:volumes:name
ストレージ名を指定spec:volumes:hostPath
保存先がpod実行サーバのフォルダspec:volumes:hostPath:typeの各種オプション
種別 説明 Directory 存在するディレクトリ DirectoryOrCreate ディレクトリが存在しなければ作成 File 存在するファイル FileOrCreate ファイルが存在しなければ作成 spec:volumes:nfs
保存先がnfsサーバのフォルダspec:volumes:configmap
configmapリソースをファイルとしてマウントさせるspec:volumes:sercret
sercretリソースをファイルとしてマウントさせる。spec:volumes:emptydir
一時的な空フォルダ演習:pod作成
- ホストにフォルダ、ファイルを作成
- 作成したフォルダをマヌントしたpodマニフェストファイルを作成
- リソース作成テストファイルとしてmessageファイルを/data/storage配下に置く。
vi /data/storage/message hello k8s下記のマニフェストファイルを作業ディレクトリ配下に置く
pod.ymlapiVersion: v1 kind: Pod metadata: name: sample spec: containers: - name: nginx image: nginx:1.17.2-alpine volumeMounts: - name: storage mountPath: /home/nginx volumes: - name: storage hostPath: path: "/data/storage" type: Directoryマニフェストファイルを元にpod作成する。
kubectl apply -f pod.yml作成したpodがマウントされているか確認する。
kubectl exec -it pod/sample sh続いてマウントしているはずであるフォルダに移動する。
cd /home/nginx/ ls cat messageうまくいったらpodを削除。
kubectl delete -f pod.yml
ReplicaSet
ReplicaSetとは、podの集合。podをスケールできる。
1つのpodに複数のdockerコンテナが入れられる。
- マニフェストファイル
主要なspecはreplicas,selector,template
replicaset.ymlapiVersion: apps/v1 kind: ReplicaSet metadata: name: nginx spec: replicas: 3 selector: matchLabels: app: web env: study template: metadata: name: nginx labels: app: web env: study spec: containers: - name: nginx image: nginx:1.17.2-alpine上記のマニフェストファイルを作業ディレクトリに配置してreplicaset.ymlを作成する。
kubectl apply -f replicaset.yml作成したreplicaset.ymlの動作確認をする。
kubectl get allNAME DESIRED CURRENT READY AGE replicaset.apps/nginx 3 0 0 9sスケールアウトを試し見る。
replicasの数値を2にしてみる(更新)NAME DESIRED CURRENT READY AGE replicaset.apps/nginx 2 0 0 9s削除。
kubectl delete -f replicaset.yml
Deployment
deployment.ymlapiVersion: apps/v1 kind: Deployment metadata: name: nginx annotations: kubernetes.io/change-cause: "First release." spec: replicas: 2 selector: matchLabels: app: web env: study revisionHistoryLimit: 14 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1 template: metadata: name: nginx labels: app: web env: study spec: containers: - name: nginx image: nginx:1.17.2-alpine上記のマニフェストファイルを作業ディレクトリに配置してDeploymentを作成する。
kubectl apply -f deployment.yml作成したDeploymentの動作確認をする。
kubectl get allロールアウトを試みる。(更新)
kubectl rollout history deploy/nginx初回は何も表示されない
deployment.extensions/nginx No rollout history found.vi deployment.yml
kubernetes.io/change-cause: ここの箇所を書き換えて再applykubectl rollout history deploy/nginx一度試みたロールアウトの履歴が確認できる。
deployment.extensions/nginx REVISION CHANGE-CAUSE 1 second release.ロールバックを試みる。(巻き戻り)
kubectl rollout undo deploy/nginxkubernetes.io/change-cause: ここの箇所を書き換えて再apply
kubectl rollout history deploy/nginx削除。
kubectl delete -f deployment.yml
Service
service.ymlapiVersion: v1 kind: Pod metadata: name: nginx labels: app: web env: study spec: containers: - name: nginx image: nginx:1.17.2-alpine --- apiVersion: v1 kind: Service metadata: name: web-svc spec: type: NodePort selector: app: web env: study ports: - port: 80 targetPort: 80 nodePort: 30000上記のマニフェストファイルを作業ディレクトリに配置してservice作成する。
kubectl apply -f service.yml作成したserviceの動作確認をする。
kubectl get allNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16h service/web-svc NodePort 10.101.233.192 <none> 80:30000/TCP 48s仮想サーバのホストにポートを指定する。
192.168.1.10:30000うまくいったらpodを削除。
kubectl delete -f service.yml
ConfigMap
![(24) 20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/cbba8851-3db3-cd3b-a71a-e0be261ea68c.jpconfigmap.ymlapiVersion: v1 kind: ConfigMap metadata: name: sample-config namespace: default data: sample.cfg: | user: tsuyoshi.tanaka type: "application" --- apiVersion: v1 kind: Pod metadata: name: sample namespace: default spec: containers: - name: sample image: nginx:1.17.2-alpine env: - name: TYPE valueFrom: configMapKeyRef: name: sample-config key: type volumeMounts: - name: config-storage mountPath: /home/nginx volumes: - name: config-storage configMap: name: sample-config items: - key: sample.cfg path: sample.cfg上記のマニフェストファイルを作業ディレクトリに配置してconfigmap作成する。
kubectl apply -f configmap.yml作成したconfigmapの動作確認をする。
kubectl get podkubectl exec -it sample shうまくいったらpodを削除。
kubectl delete -f configmap.yml
Secret
![(25) 28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/fc4be54e-0d61-2a77-5bb5-3c8a6b774314.jpsercret.ymlapiVersion: v1 kind: Secret metadata: name: sample-secret data: message: SGVsbG8gV29ybGQgIQ== # echo -n 'Hello World !' | base64 keyfile: WU9VUi1TRUNSRVQtS0VZ # cat ./keyfile | base64 --- apiVersion: v1 kind: Pod metadata: name: sample namespace: default spec: containers: - name: sample image: nginx:1.17.2-alpine env: - name: MESSAGE valueFrom: secretKeyRef: name: sample-secret key: message volumeMounts: - name: secret-storage mountPath: /home/nginx volumes: - name: secret-storage secret: secretName: sample-secret items: - key: keyfile path: keyfile上記のマニフェストファイルを作業ディレクトリに配置してsercret作成する。
kubectl apply -f secret.yml鍵ファイルを使って、sercretを暗号化する。
kubectl create secret generic sample-sercret作成したsercretの動作確認をする。
kubectl get secret作成したsercretの詳細な動作確認をする。
kubectl get secret/sample-sercret -o yamlsecret.ymlを削除。
kubectl delete -f secret.yml
永続データ(PersistentVolume,PersistentVolumeClaim)
storage.ymlapiVersion: v1 kind: PersistentVolume metadata: name: volume-01 labels: env: study spec: storageClassName: slow accessModes: - ReadWriteOnce capacity: storage: 1Gi persistentVolumeReclaimPolicy: Retain hostPath: path: "/data/storage" type: Directory --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: volume-claim labels: env: study spec: storageClassName: slow accessModes: - ReadWriteOnce resources: requests: storage: 1Gi上記のマニフェストファイルを作業ディレクトリに配置してstorage作成する。
kubectl apply -f storage.ymlstorage.ymlの動作を確認する。
kubectl get pvc,pvマウントされていることが確認できる。
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE persistentvolumeclaim/volume-claim Pending slow 73s NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE persistentvolume/volume-01 1Gi RWO Retain Pending slow 74s削除。
kubectl delete -f storage.yml
StatefulSet
statefulset.ymlapiVersion: v1 kind: PersistentVolume metadata: name: volume-01 spec: storageClassName: slow accessModes: - ReadWriteMany capacity: storage: 1Gi persistentVolumeReclaimPolicy: Retain hostPath: path: /data/storage type: Directory --- apiVersion: v1 kind: Service metadata: name: sample-svc spec: clusterIP: None selector: app: web env: study ports: - port: 80 targetPort: 80 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: nginx spec: replicas: 1 selector: matchLabels: app: web env: study revisionHistoryLimit: 14 serviceName: sample-svc template: metadata: name: nginx labels: app: web env: study spec: containers: - name: nginx image: nginx:1.17.2-alpine volumeMounts: - name: storage mountPath: home/nginx volumeClaimTemplates: - metadata: name: storage spec: storageClassName: slow accessModes: - ReadWriteMany resources: requests: storage: 1Gi上記のマニフェストファイルを作業ディレクトリに配置してstatefulset.yml作成する。
kubectl apply -f statefulset.yml作成したstatefulset.ymlの動作確認をする。
kubectl get all続いて、centospodを起動してアクセスする。
kubectl run debug --image-centos:7 -it --rm --restart=Never -- shうまくいったらstatefulset.ymlを削除。
kubectl delete -f statefulset.yml
Ingress
apiVersion: v1 kind: Service metadata: name: web-svc spec: selector: app: web env: study ports: - port: 80 targetPort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 2 selector: matchLabels: app: web env: study template: metadata: name: nginx labels: app: web env: study spec: containers: - name: nginx image: nginx:1.17.2-alpine --- apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: frontend annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/ssl-redirect: "false" spec: rules: - http: paths: - path: / backend: serviceName: web-svc servicePort: 80上記のマニフェストファイルを作業ディレクトリに配置してingress作成する。
kubectl apply -f ingress.yml作成したingressの動作確認をする。
kubectl get ing,svc,deploy下記のように外部アドレスが表示されない場合、設定されるまで数分待つ。
NAME HOSTS ADDRESS PORTS AGE ingress.extensions/frontend * 80 3m8s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 15h service/web-svc ClusterIP 10.110.116.66 <none> 80/TCP 3m8s NAME READY UP-TO-DATE AVAILABLE AGE deployment.extensions/nginx 0/2 2 0 3m9sうまくいったらingress.ymlを削除。
kubectl delete -f ingress.yml
本セクションではKubernetesリソースの使い方を学習しました。
このまとめでは各リソースのサンプルコードおよびコード中にポイントとなる箇所をまとめます。◆ワークロード
○Pod
apiVersion: v1
kind: Pod
metadata:
name: sample
spec:
containers:
- name: nginx
image: nginx:1.17.2-alpine
volumeMounts:
- name: storage
mountPath: /home/nginx
volumes:
- name: storage
hostPath:
path: "/data/storage"
type: Directory○ReplicaSet
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: web
env: study
template: # Podと同じものを記述
metadata:
name: nginx
labels:
app: web
env: study
spec:
containers:
- name: nginx
image: nginx:1.17.2-alpine○Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
annotations:
kubernetes.io/change-cause: "First release."
spec:
replicas: 2
selector:
matchLabels:
app: web
env: study
revisionHistoryLimit: 14 # デフォルト 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 余分に生成してよいPod数
maxUnavailable: 1 # 一度に消失してよいPod数
template:
metadata:
name: nginx
labels:
app: web
env: study
spec:
containers:
- name: nginx
image: nginx:1.17.2-alpine○StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: web
env: study
revisionHistoryLimit: 14
serviceName: sample-svc # HeadlessServiceと紐づける
template:
metadata:
name: nginx
labels:
app: web
env: study
spec:
containers:
- name: nginx
image: nginx:1.17.2-alpine
volumeMounts:
- name: storage
mountPath: home/nginx
volumeClaimTemplates: # PersistentVolumeClaimと同じものを記述
- metadata:
name: storage
spec:
storageClassName: slow
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi◆サービス
○Service
apiVersion: v1
kind: Service
metadata:
name: web-svc
spec:
type: NodePort # ClasterIP(デフォルト), NodePort, LoadBalancer, ExternalName
selector:
app: web
env: study
ports:
- port: 80 # 受付ポート
targetPort: 80 # 転送先ポート
nodePort: 30000 # ノード上にマッピングするポート(type: NodePort 時のみ)○Ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: frontend
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: web-svc
servicePort: 80◆設定
○ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: sample-config
data:
sample.cfg: |
user: tsuyoshi.tanaka
type: "application"○Secret
apiVersion: v1
kind: Secret
metadata:
name: sample-secret
data:
message: SGVsbG8gV29ybGQgIQ== # echo -n 'Hello World !' | base64
keyfile: WU9VUi1TRUNSRVQtS0VZ # cat ./keyfile | base64◆ストレージ
○PersistentVolume
apiVersion: v1
kind: PersistentVolume
metadata:
name: volume-01
labels:
env: study
spec:
storageClassName: slow
accessModes:
- ReadWriteOnce # ReadWriteOnce, ReadOnlyMany, ReadWriteMany
capacity:
storage: 1Gi
persistentVolumeReclaimPolicy: Retain # Retain, Delete, Recycle(非推奨)
hostPath:
path: "/data/storage"
type: Directory○PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: volume-claim
labels:
env: study
spec:
storageClassName: slow
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi記述のポイントはおさえられたでしょうか?
これから実践に入っていく際、基本となりますので忘れたときにはここへ立ち返って復習しながら進めましょう!