- 投稿日:2021-03-29T22:38:54+09:00
【Windows10Home】DockerによるPython開発環境の構築
Windows 10 Homeで特定バージョンのPython保持しなければならなくなったので、その際やったことを記事にまとめます。
オーソドックスにWSL2でDockerを動かし、コンテナ上にPython環境を構築してみようと思います。対象読者
開発初心者の方。特にPython。
そもそもWSLって? Dockerって名前は聞いたことあるけど、実際どんなものなの? という方にも(なるべく)理解してもらえる(といいなぁ)よう、頑張ります。対象マシン
Windows 10 Home
x64システムの場合、バージョン 1903 以降、ビルド 18362 以上が必要です。そもそも
なぜ特定バージョンのPythonを保持しなければならなくなったのかといえば、そのバージョンでしか(まともに)動かない機械学習Modelを作ってしまったからです。
だからPythonのアップデートはしたくないんだけど、別のModelでは別のバージョンを使いたい……なんてことは、Pythonの開発をやっていると稀によくあります。
pyenvなどでも1つのマシンに異なるバージョンを保持することができますが、Dockerのコンテナにプロジェクトの開発環境をまるっと保持してしまえばよりシンプルに、かつ移植性も高い環境を構築できるため、こちらを採用しました。
(ぶっちゃけpyenvよくわかってない)でもその前に
ただ、初心者は特にですが、必要性がなければこんなことをする必要もないです。
機械学習といえばGPUだ! Ubuntuだ! となりいきなり壮大な環境構築を頑張ろうとして躓いて嫌になって……。てなるのも悲しいので。
それでもPythonの開発ではライブラリの導入を含めたトライ&エラーが頻発します。
そのたびにインストール&アンインストールを繰り返しているとローカルの開発環境がぐっちゃぐちゃに汚れ、このライブラリどこにパス通ってるんだ……? なんてことにもしばしば。
そうなったら新規一転、開発環境を仮想化してしまうのも手です。あとは自然言語処理でMeCab使いたいけど、Windowsだと文字コードでバグりまくる……という場合も、簡単にLinux系の環境を用意できるのも利点ですね。
開発初心者の方はこんな風に、必要に迫られた段階でステップアップとして取り組むと良いと思います。用語
何となく仮想環境を構築したい理由はわかったよ。じゃあWSLって? Dockerって? という方に。
Dockerとは
仮想化技術の一つです。
非常に手軽にWEBサーバーやAPサーバー、DBサーバーをデプロイできることからWEB開発の現場では広く使われている(らしい)技術です。おれWEB畑じゃないからね。
Hyper-VやVirtualBoxと何が違うの? と思われる方がいるかもしれませんが、これらは物理マシンのネットワークスイッチなどをエミュレートできるのに対し、DockerではベースとなるOSと完全に分離せず、OSのカーネル上にコンテナを配置する形をとります。
(前者をホスト型仮想化、後者をコンテナ型仮想化といいます)
例えばHyper-Vではホストとは異なるOSを積んだり、個別にネットワークアダプタを割り当てることが可能ですが、それらの点でいうとDockerは劣ります。
なのになぜDockerを使うのかと言われれば、やはりその軽量さ、手軽さが大きな理由でしょうか。
DockerではOS上にほかのプロセスと切り離された環境にコンテナを作るので、仮想環境の動作をホスト型仮想化よりも少ないリソースで実現できるのです。WSL(2)とは
Windows Subsystem for Linuxの略で、そのまんま、Windows上でLinuxを動かすための技術です。
じゃあやっぱHyper-Vでいいじゃん! って感じですが、Windows 10 HomeじゃHyper-V使えないし、さらにいうとHyper-Vより少ないリソースでLinuxを動かすことができて、んでもって動作も軽量軽快。
個人的に一番違いを感じるのは起動ですね。
また今回はDocker Desktop for Winodwsという製品を使いたいのですが、本来こちらはHyper-Vの仮想化とネットワークを利用します。
前述の通りHomeではHyper-Vが使えないのですが、WSL2にUbuntuをインストールすることで、Docker Desktop for Windowsのバックエンドとして機能させることができるのです。要はWSL2でUbuntuを動かして、そこにDockerをインストールするってことですね。
環境のイメージ
以上を踏まえ、今回はこんなイメージの環境を構築してみたいと思います。
やっと図が出てきた。ホストのWindowsでWSL2を起動し、そこでUbuntuを動かします。UbuntuやDockerの制御はPowerShell等からでもできるのですが、今回はWindows Terminalからコントロールします。
そのUbuntu上にDocker(Docker Desktop for Windows)を導入。
Docker上にコンテナを配置し、それらを開発環境として利用します。
今回はAnacondaのDockerイメージをDockerHubから引っ張ってきます。DockerHubってのはDockerのコンテナを公開できる、GitHubみたいなもんだね。
んでAnacondaのコンテナでJupyter Labを動かし、Windowsのブラウザから操作したりプロジェクトをVS Codeでいじくったりできるようになろうってのが今回の目標です。ちょっと注意
ここまで言っておいて水差すつもりはないんですけど、製品版のWindowsではWSL2をバックエンドとしたDockerコンテナではGPUを使えません。
(2021年3月19日現在)
Insider Previewならできるのですが、そちらは自己責任となりますのでご注意を。
自分はGPUを使うプロジェクトに関してはローカルでやりくりしています。WSL2のインストール
やぁ、前置きがウルトラ長くなってしまった。
まずはWSL2のインストールからはじめましょ。
公式ドキュメント:https://docs.microsoft.com/ja-jp/windows/wsl/install-win10コマンドラインからのインストールは現在(2021/3/19)プレビュー版でしか利用できないようです。
PowerShellの起動
Windowsの検索機能で「PoweShell」と入力します。表示されたアイコンを右クリックし、「管理者として実行」を選んでください。
Linux用Windowsサブシステム、仮想マシンの機能の有効化
起動したPowerShellから下記のコマンドを入力し、必要な機能を有効化します。
Linux用Windowsサブシステムdism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart仮想マシンの機能
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestartどちらもすぐに処理は完了すると思います。
Linuxカーネル更新プログラムパッケージのダウンロード
以下のリンクからLinuxカーネル更新プログラムパッケージをダウンロードします。
https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msiダウンロードしたパッケージをダブルクリックし、インストールします。
手順に従って進み、以下の画面となればOKです。
WSL2を既定のバージョンとして設定
再度管理者としてPowerShellを開いて、次のコマンドを実行します。
wsl --set-default-version 2新たにLinux系OSをインストールする際に使用するWSLの規定バージョンを2に指定しています。
これでひとまずWSL2の準備は完了。
Ubuntuのインストール
続いてはWSL2に乗っけるOS(Linuxディストリビューション)をインストールします。
WSL2ではDebian GNU/Linuxなどのディストリビューションも利用可能とのことですが、今回は機械学習の開発環境を構築することが目的なのでよく使われるUbuntuを使うことにします。
バージョンは16.04 LTS / 18.04 LTS / 20.04 LTSから選びます。
自分は20.04 LTSをインストールしますが、それ以外のバージョンでも手順は同じ(はず)です。Microsoft StoreからUbuntuをダウンロード
スタートメニューから「Microsoft Store」を開き、検索窓に「Ubuntsu」と入力します。
(MSのアカウントでサインインしていなくてもDLできました)
Ubuntuの起動
インストールが完了すると「インストール」のボタンが「起動」に変わっているので、クリックしてUbuntuを起動します。
Ubuntuを起動すると初期化が行われ、続いてユーザー名とパスワードの入力が求められます。
ご自身のものを入力してください。あとちなみにスタートメニューに「Ubuntu 20.04 LTS」が追加されていると思います。
起動状況の確認
念のためPowerShellからUbuntuの起動状況を確認しましょう。
(別に管理者権限で開かなくてもいいです)
以下のコマンドを実行してください。wsl --list --verboseこれはWSLにインストールされているLinuxディストリビューションの一覧と起動状況、使用するWSLのバージョンを表示するコマンドです。
Ubuntu-20.04がVERSION「2」としてインストールされていますね。
大丈夫そうです。Windows Terminalのインストール(おまけ)
これはオプションなので別にやらなくてもいいんですけど、自分はUbuntuの操作はWindows Terminalから行っています(結構使いやすい)。
Windows TerminalもMicrosoft Storeからインストールできますできます。
(検索窓に「Windows Terminal」と入力してください)
用途としてはUbuntuの制御がメインなので、起動時にUbuntuのシェルが立ち上がるよう規定値を変更します。
タブの「▽」をクリックし、「設定」を選択してください。
「Setting.json」というjsonファイルが開かれます。
上のほうに「defaultProfile」という項目があります。
ここに起動時に立ち上げたいシェルのguidを入力することで規定値を変更することができます。
少しスクロールすると「profiles」→「list」というところに各シェルの情報が格納されているのがわかります。
Ubuntuがインストールされていれば「"name": "Ubuntu-20.04"」の項目があるはずなので、そのguidをコピーし、先ほどのdefaultProfileの値に貼り付けます。
これでWindows Terminalを起動するとデフォルトでUbuntuのシェルが立ち上がるようになりました。
Docker Desktop for Windowsのインストール
バックエンド環境が準備できたところで、Dockerをインストールしましょう。
公式ドキュメント:https://docs.docker.jp/docker-for-windows/install.htmlインストーラーのダウンロード
インストーラーはDocker Hubからダウンロードできます。
https://hub.docker.com/editions/community/docker-ce-desktop-windows/「Get Docker」をクリックするとダウンロードが始まります。
特にSign upしなくてもDLできます。インストール
ダウンロードしたインストーラーをダブルクリックして起動します。
「Install required Windows Components for WSL 2」にチェックし、「OK」をクリックします。
試しにDockerを起動してみましょう。
もちろん空っぽです。
このあとコンテナ入れるので、チュートリアルはスキップして良いです。
Dockerディスク領域の変更(オプション)
Docker Desktopをインストールすると問答無用でシステムドライブに仮想環境が作られます。
↑の手順でもマウントするパスの指定とかなかったしね。
コンテナを立てていくとCドライブの容量を圧迫してしまうので、データドライブに領域を移します。なおWSLのインストール一覧は下記のコマンドで確認することができます。
wsl --listWindows Terminalでの実行結果です。このとき接続先のシェルはPowerShellにしてください。
(先の手順でデフォルトがUbuntuになっているので)
領域を移したいのはこの「docker-desktop-data」ってやつです。
ちなみに上記のイメージの実態は
%LocalAppData%\Docker\wsl\distro\ext4.vhdx
というものです。
エクスプローラーで%LocalAppData%\Docker\wsl\distro
と入力すると、ext4.vhdx
というファイルがあります。
(多分デフォルトだとC:\Users\(ユーザー名)\AppData\Local\Docker\wsl\distro
とかじゃないかな)
あ、ちなみにvhdx
はVirtualHardDisk
って意味ね。Docker / WSLの停止
まずはDocker Desktopを停止します。
タスクバーの「△」を選択し、Dockerのクジラみたいなアイコンを右クリックすると操作一覧が表示されるので「Quit Docker Desktop」を選択します。
続いてPowerShellで下記のコマンドを実行します。
wsl --shutdown念のため起動状況を確認します。
wsl --list --verboseSTATEがすべて「Stopped」になっていればOKです。
データのエクスポート
docker-desktop-data
の移動先のフォルダを作っておきます。
データドライブにD:\01_Docker
というフォルダを予めつくっておきました。フォルダ名は気にしないでください。下記のコマンドで、上記フォルダの中に
docker-desktop-data.tar
というファイルをエクスポートします。wsl --export docker-desktop-data D:\01_Docker\docker-desktop-data.tarコンテナは空っぽの状態なんで、すぐに終わります。
docker-desktop-dataの登録の解除
WSLにおけるdocker-desktop-dataの登録を解除します。
wsl --unregister docker-desktop-data.tarファイルのインポート
上記でデータドライブにエクスポートしておいた.tarファイルをインポートします。
D:\01_Docker
フォルダの直下にdata
フォルダを作成します。
下記のコマンドを実行し、D:\01_Docker\docker-desktop-data.tar
ファイルをD:\01_Docker\data
フォルダにインポートします。> wsl --import docker-desktop-data D:\01_Docker\data D:\01_Docker\docker-desktop-data.tar
D:\01_Docker\data
フォルダにext4.vhdx
が作成されています。
WSL / Dockerの起動
WSLとDockerを起動しましょう。
WSLはPowerShellでwsl
と入力すれば起動します。
DockerはアイコンをクリックすればOK。Dockerコンテナの作成
ちょっと話が脇道にズレてしまいましたが、いよいよ最終目的である仮想開発環境を構築しましょう!
冒頭のイメージ図でもふれたとおり、今回はDocker HubからAnacondaのコンテナをダウンロードします。作業フォルダの準備~Dockerfileの作成
Dockerではコンテナを作るときに
Dockerfile
というファイルを作成し、そこにどんな構成のコンテナとするか~といった情報をコードとして記述します。
コンテナを立ち上げる時にDockerがこのファイルを参考にセットアップしてくれるんですね。まずはそのコンテナにおける作業フォルダを作成します。
本格的な運用をする場合には1プロジェクトにつき1コンテナとすることが多いので、コンテナ名=プロジェクト名するのが分かりやすいでしょう。
今回はD:\Project\202103_TestProject
というフォルダを作成しました。
ここでは半角英数にしておいたほうが賢明です。
特に スペースは全角半角問わずやめておいたほうが良いでしょう。作成したフォルダの直下で右クリック→新規作成→テキストドキュメントを選択します。
作成したファイル名を「Dockerfile」に変更します。
このとき、 「.txt」の拡張子を削除します。
Dockerfileに拡張子はないのです。
Dockerfileの記述
作成したDockerfileに「どんなコンテナを作るのか」という情報を記述していきます。
DOckerfileを選択し右クリック→プログラムから開くを選び、好きなテキストエディタから編集してください。今回は次のような命令を記述していきます。
FROM continuumio/anaconda3:2019.03 RUN pip install --upgrade pip && pip install Keras && pip install tensorflow WORKDIR /workdir EXPOSR 8888 ENTRYPOINT ["jupyter-lab", "--ip=0.0.0.0", "--port=8888", "--no-browzer", "--allow-root", "--NotebookApp.token=''"] CMD ["--notebook-dir=/workdir"]一つ一つ見ていきましょう。
FROM continuumio/anaconda3:2019.03
ここでDocker Hubから「2019.03時点のAnaconda3を引っ張って来いよ」と明示しています。
RUN pip install --upgrade pip && pip install Keras && pip install tensorflow
その後実行するコードです。
イメージとしてはcmdから実行すべきコマンドを記述している感じ。
WORKDIR /workdir
命令を実行するときのカレントディレクトリを指定します。
上記によりコンテナに/workdir
が作成され、各種命令はこの中で実行されることになります。
EXPOSE 8888
ネットワーク上のポートを指定します。
ENTRYPOINT ["jupyter-lab", "--ip=0.0.0.0", "--port=8888", "--no-browzer", "--allow-root", "--NotebookApp.token=''"]
実行対象に関する設定です。
今回はコンテナ上で起動するJupyter LabをホストのWindowsから利用したいのでそれに関する設定を行っています。
ローカルで完結する環境を想定しているためトークン認証は無効としていますが("--NotebookApp.token=''")、例えばクラウドで立ち上げる等であれば設定が必要でしょう。
CMD ["--notebook-dir=/workdir"]
最後にJupyter labの作業ディレクトリを先ほど作成した/workdirに紐づけます。
以上で命令の記述は完了です!
保存してエディタを閉じます。docker-compose.ymlファイルの作成
次にアプリケーションを構成するサービスを「Docker-compose.yml」というファイルに記述します。
今回はDockerの起動にはDocker Composeというツールを使用します。
これは複数コンテナを定義し、実行するDockerアプリケーションを管理するためのツールです。YAMLというファイルにアプリケーションの各サービスの設定を記述することによって、Docker起動時にYAMLファイルを呼び出すだけで簡単にコンテナの生成、起動を行うことができます。
先ほど作成したDockerfileと同じディレクトリに、
docker-compose.yml
というファイルを作成してください。そこに以下のように記述します。
services: dev: build: context: . dockerfile: Dockerfile image:project01 ports: - "8080:8888" volumes: - .:/workdirimageにはご自身のプロジェクト名を入力してください。
また起動対象となるDockerfileもbuild内で指定します。そのためdocker-compose.ymlとDockerfileは同じディレクトリにないといけませんので、注意。
Dockerfileと同じくvolumesには作業ディレクトリとして/workdirを指定しましょう。ちなみに今回は割愛しますが、docker-compose.ymlファイルを使用しなくとも、シェルから
docker run
というコマンドを実行しても起動できますよ。コンテナの起動
これでコンテナを起動する準備ができました。
Powershellを起動し、カレントディレクトリをDockerfile、docker-icompose.ymlが置かれたフォルダに移動します。cd D:\Project\202103_TestProject続いて下記のコマンドを実行します。
docker-compose upJupyter Labの起動
WindowsからコンテナのJupyter Labに接続しましょう。
コンテナが起動した状態で任意のブラウザを起動し、localhost:8080
と入力してください。
Jupyter Labが起動すれば成功です!
Jupyterのナビゲーターを見ればわかる通り、JupyterのカレントディレクトリはそのままDockerfile、docker-compose.ymlが置かれたフォルダとなっています。
このフォルダの中身をコンテナは認識してくれますので、試しにこの直下に「01_Input」「02_Source」「03_Model」「04_Output」というフォルダを作成してみます。
今度は逆にJupyter LabからPythonのNotebookを作ってみましょう。
「02_Source」に入り、Python Notebookを作成します。
Windows側のエクスプローラーから「02_Source」の中を見ると、作成した.ipynbファイル(とチェックポイント)があることが分かります。
これで無事WindowsとDockerコンテナの同期が取れていることが確認できました!
お疲れ様です、全作業完了です!
あとはもう、イカしたModelを作りまくって世の中に貢献しちゃってください。
- 投稿日:2021-03-29T19:34:08+09:00
ECSにデプロイしたコンテナが一定時間ごとに落ちる?
背景
ECSにデプロイしたAPIサーバの役割を果たすタスクが一定時間ごとに落ちて毎回ECS agentによって立ち上げられるという事象を観測した。大元の原因を特定するのに手間取ったため、メモとして残しておく。
状況整理
ECSはALBのターゲットとして登録してしていたので、ALBによるヘルスチェックが行われている。また、ECSのタスク定義でコンテナヘルスチェックも行なっている。
このような場合、以下のような現象が観測される。
- ALBのヘルスチェックが失敗している
- ECSのコンテナヘルスチェックが失敗している
- サーバプロセスがexitしている
これらの現象は相互に影響を与え合う。例えば、サーバプロセスがexitするとECSのコンテナヘルスチェックやALBのヘルスチェックが失敗する。また、ネットワークの設定ミスがあった場合、サーバプロセスは動いているのにALBによるヘルスチェックが失敗して、ALBがECS agentにコンテナを落とすことを命令し、サーバプロセスがSIGTERMを受け取ってexitするかもしれない。さらに、ECSのコンテナヘルスチェックの設定ミスで、サーバプロセスは動いているのにコンテナヘルスチェックが失敗して、サーバプロセスにSIGTERMが送られるかもしれない。
すなわち、大元の原因を突き止めるにはちょっとした工夫が必要である。絞り込み1
まず重要なヒントは、コンテナが起動されて落ちるまでの時間が毎回一定かどうか、ということである。
一定でなければ、サーバプロセスが自らexitしている可能性が高い。その場合は、コンテナからCloudWatch logsなどにログを送信してエラーがおきていないかを確認する必要がある。これは比較的わかりやすい。
コンテナが起動されて落ちるまでの時間が毎回一定である場合は、さらに絞り込みを行う。絞り込み2
コンテナが起動されて落ちるまでの時間が毎回一定であれば、(サーバプロセスは正常であるが)ネットワークやヘルスチェックの設定にミスがある可能性が大きい。
最初にやるべきことは、サーバプログラムへのリクエストのログをCloudWatch logsなどに送信してログを見れる状態にすることである。このリクエストログにはUser-Agentが含まれていなければならない。
User-Agentを含むリクエストログが見れる状態にできたら、タスクを再実行してみる。
ECSに設定したヘルスチェックコマンドがcurlを使ったものであれば、User-Agentの部分がcurlであるログが存在するはずである。
同じようにALBによるヘルスチェックが正しく行われていれば、リクエストログのUser-Agentが"ELB-HealthChecker"となっているログが存在するはずである。両方のヘルスチェックが設定されていた場合は、それぞれに対して以下の検証を行う。もし、設定したヘルスチェックコマンドに対応するUser-Agent値がログに含まれていれば、ネットワークの設定は正しいがヘルスチェックの設定ミスが原因でサーバプロセスにSIGTERMが送られている可能性が高い。この場合、ヘルスチェックコマンドの設定は正しいことが保証されている。ヘルスチェックの設定にはコマンド以外にも、タイムアウトやインターバルやリトライ回数といったパラメータがある。ここでは、それらのパラメータ設定が間違っていることを疑う。ここで大事なのは、各ヘルスチェックの設定において、最短でUnhealthyになるまでの時間を求めることである。例えば、ECSのコンテナヘルスチェックでタイムアウトが20s、インターバルが100s, リトライが3回、スタートピリオドが30sという設定がなされていたとき、最短でUnhealthyになるのはインターバル100sのヘルスチェックが3回連続失敗する場合なので、(100 * (3 - 1)) + 20 + 30で250sである。もし、ECSのコンテナヘルスチェクとALBのヘルスチェックの設定が異っていれば、コンテナが起動して落ちるまでの時間と比較することで、どちらのヘルスチェックの設定を直すべきかがわかる。ここまでわかれば解決は容易いだろう。
一方、設定したヘルスチェックコマンドに対応するUser-Agent値がログに含まれていなければ、さらに絞り込みを行う。
絞り込み3
ヘルスチェックがなされた痕跡がリクエストログに残っていない場合、2つの可能性がある。
- ネットワークの設定ミスで、ヘルスチェックのリクエストがコンテナまで到達していない
- ネットワークの設定は正しいが、ヘルスチェックコマンドの設定が間違っている。
2の場合は、大抵の場合、以下のいずれかに該当するであろう。
- リクエストが送られるパスに対する応答が200以外のコードを返す。
- リクエストが送られるポート番号が間違っている。
- ECSのヘルスチェックコマンドでcurlを使っているが、curlがコンテナにインストールされていない。(alpineにはcurlが含まれていない。)
- ECSのヘルスチェックコマンドの設定形式が間違っている。
4のケースはデバックがしづらいがAWS::ECS::TaskDefinition HealthCheckやDocker公式ドキュメント CreateContainerを慎重に読み込むことでミスを見つけることは可能である。
これらに当てはまらない場合は、1.ネットワークの設定ミス、を疑う。ネットワークの設定ミスには、SubnetのNetworkACL設定や、ECS ServiceのSecurity group設定、タスク定義のport mapping設定など、様々な設定値が関係してくるので、一つ一つの設定を慎重に疑う必要がある。また、ネットワーク設定のデバッグは、踏み台サーバからリクエストを送ってみるなどの手段が有効である。
まとめ
上記の流れで大抵のケースは捕捉できると思う。
- 投稿日:2021-03-29T18:21:23+09:00
DockerイメージのMySQL5.6と5.7はタイムゾーン設定が異なる
MySQL5.6から5.7に移行するにあたって、開発環境を整理していたらDockerイメージのデフォルトのタイムゾーンが変わっていることに気付いた。
MySQL 5.6のタイムゾーン設定
5.6のデフォルトのタイムゾーンは以下の通り設定されていた。
mysql> show variables like '%time_zone%'; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | UTC | | time_zone | SYSTEM | +------------------+--------+ 2 rows in set (0.00 sec)そのため、Dockerfileで以下のコマンドを実行して、タイムゾーンを変更していた。
RUN cp -p /usr/share/zoneinfo/Japan /etc/localtimeMySQL 5.7のタイムゾーン設定
5.7のデフォルトのタイムゾーンは以下の通りだった。
mysql> show variables like '%time_zone%'; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | JST | | time_zone | SYSTEM | +------------------+--------+ 2 rows in set (0.00 sec)system_time_zoneがロケールの時間帯を採用するように変更されたらしい。
これによって最初から日本時間で処理されるようになった。
- 投稿日:2021-03-29T14:32:48+09:00
コンテナLambdaをデプロイしてみた(躓いたポイントとリソース削除)
はじめに
AWS builders-flashにコンテナLambdaの記事が出ていたので試してみました。
躓いたポイントと試した後に実行したリソース削除コマンドだけ書いておきます。
躓いたポイント
awscli 2.1.6 未満だとコマンド実行エラーになる
aws lambda create-function \
--function-name func1-container \
--package-type Image \
--code ImageUri=\${ACCOUNTID}.dkr.ecr.\${REGION}.amazonaws.com/func1@\${DIGEST} \
--role ${ROLE_ARN}コンテナLambdaは新しくサポートされた機能なので、バージョンは最新化すべきですね。
2.1.5と2.1.6の必須パラメータの違い
bash#必須項目が変わっているので、2.1.5以前でコンテナLambda作成コマンドを叩くとエラーになります docker run --rm -ti -v ~/.aws:/root/.aws amazon/aws-cli:2.1.5 lambda create-function help #コマンド結果抜粋 SYNOPSIS create-function --function-name <value> --runtime <value> --role <value> --handler <value> [--code <value>] [--description <value>] docker run --rm -ti -v ~/.aws:/root/.aws amazon/aws-cli:2.1.6 lambda create-function help #コマンド結果抜粋 SYNOPSIS create-function --function-name <value> [--runtime <value>] --role <value> [--handler <value>] [--code <value>] [--description <value>]amazon/aws-cliでawsコマンドを実行していると環境変数が正しくセットされない
REGION=\$(aws configure get region)
ACCOUNTID=\$(aws sts get-caller-identity --output text --query Account)amazon/aws-cliを利用した場合としない場合で出力結果が違うよう。
ローカルのawscliとamazon/aws-cliの出力結果の違い
bash#amazon/aws-cliを利用すると余計な内容が出力されているので、amazon/aws-cliの実行結果を直接環境変数に入れると、環境変数を使う際にコマンド実行エラーが起きる #amazon/aws-cliを使ってもよいやり方があるのかも知れないですが、今回はローカルにawscliを入れて実行しました。 alias aws #aliasがない状態 aws sts get-caller-identity --output text --query Account | cat -e #コマンド結果 XXXXXXXXXXXX$ alias aws='docker run --rm -ti -v ~/.aws:/root/.aws amazon/aws-cli:2.1.32' aws sts get-caller-identity --output text --query Account | cat -e #コマンド結果 ^[[?1h^[=^MXXXXXXXXXXXX^[[m^M$ ^M^[[K^[[?1l^[>%IAMRoleのポリシー不足で権限エラー
できるだけ最小権限で実行したく、ポリシーを見直しました。
今回設定したポリシー
bash"ecr:BatchCheckLayerAvailability" "ecr:BatchDeleteImage" "ecr:CompleteLayerUpload" "ecr:CreateRepository" "ecr:DeleteRepository" "ecr:GetRepositoryPolicy" "ecr:InitiateLayerUpload" "ecr:ListImages" "ecr:PutImage" "ecr:SetRepositoryPolicy" "ecr:UploadLayerPart" "iam:CreateRole" "iam:DeleteRole" "iam:PassRole" "lambda:CreateFunction" "lambda:DeleteFunction" "lambda:InvokeFunction"コンテナLambdaをデプロイしてみる
ここはAWS builders-flashと同じなので、ここには記載しません。
不要リソースを削除
試したあとはリソース削除しておきたいので削除コマンドを記載。
bashaws lambda delete-function --function-name func1 aws lambda delete-function --function-name func1-container aws ecr delete-repository --repository-name func1 --force aws iam delete-role --role-name lambda-ex
- 投稿日:2021-03-29T12:08:02+09:00
ゼロからのOS自作入門をMacで勉強する方法
ゼロからのOS自作入門をMacで読み進めたい
本書ではLinux(Ubuntu)を開発環境に選んでおり、
WindowsのWSLを使った方法を紹介しているが、Macでの方法は記載されていなかった。私の環境
- macOS Big Sur(ver. 11.2.2)
- Docker Engine v20.10.2
Docker上で環境を作っていく
Docker上のUbuntuでビルドしたOSをQEMUで起動させることにした。
今回作ったDockerfile
$ cat works/os/DockerfileFROM ubuntu:18.04 MAINTAINER meruneru ENV IMAGE_NAME=MikanOS RUN apt-get update RUN apt-get install -y vim \ build-essential \ python3 \ git \ okteta \ tmux \ dosfstools # https://github.com/uchan-nos/mikanos-build RUN cd $HOME; \ git clone https://github.com/uchan-nos/mikanos-build.git osbook; \ apt install -y ansible; \ cd $HOME/osbook/devenv; \ ansible-playbook -K -i ansible_inventory ansible_provision.yml CMD ["/bin/bash"]Dockerfileからイメージを作成する
$ docker build -t os works/osDocker内のGUIアプリをMacOS側に出力するために・・・
XQuartz(X11サーバ)を別途インストールし、XQuatzの環境設定のセキュリティタブで、
"ネットワーク・クライアントからの接続を許可"にチェックを入れておく。
Dockerイメージを起動する
以下のコマンドでOSを起動させることができる。
起動後に書籍に載っているコマンドがインストールされていれば、環境構築完了コマンドが長いので、私は下記ファイルをシェルスクリプトにして起動してる。
docker run -it --rm \ --privileged \ -e DISPLAY=$(hostname):0 \ -v ~/.Xauthority:/root/.Xauthority \ -v $HOME/works/os:/root/os/ \ os
- 投稿日:2021-03-29T12:08:02+09:00
ゼロからのOS自作入門をMacで勉強する方法 (Docker使用)
ゼロからのOS自作入門をMacで読み進めたい
本書ではLinux(Ubuntu)を開発環境に選んでおり、
WindowsのWSLを使った方法を紹介しているが、Macでの方法は記載されていなかった。私の環境
- macOS Big Sur(ver. 11.2.2)
- Docker Engine v20.10.2
Docker上で環境を作っていく
Docker上のUbuntuでビルドしたOSをQEMUで起動させることにした。
今回作ったDockerfile
$ cat works/os/DockerfileFROM ubuntu:18.04 MAINTAINER meruneru ENV IMAGE_NAME=MikanOS RUN apt-get update RUN apt-get install -y vim \ build-essential \ python3 \ git \ okteta \ tmux \ dosfstools # https://github.com/uchan-nos/mikanos-build RUN cd $HOME; \ git clone https://github.com/uchan-nos/mikanos-build.git osbook; \ apt install -y ansible; \ cd $HOME/osbook/devenv; \ ansible-playbook -K -i ansible_inventory ansible_provision.yml CMD ["/bin/bash"]Dockerfileからイメージを作成する
$ docker build -t os works/osDocker内のGUIアプリをMacOS側に出力するために・・・
XQuartz(X11サーバ)を別途インストールし、XQuatzの環境設定のセキュリティタブで、
"ネットワーク・クライアントからの接続を許可"にチェックを入れておく。
Dockerイメージを起動する
以下のコマンドでOSを起動させることができる。
起動後に書籍に載っているコマンドがインストールされていれば、環境構築完了コマンドが長いので、私は下記ファイルをシェルスクリプトにして起動してる。
docker run -it --rm \ --privileged \ -e DISPLAY=$(hostname):0 \ -v ~/.Xauthority:/root/.Xauthority \ -v $HOME/works/os:/root/os/ \ os
- 投稿日:2021-03-29T11:55:00+09:00
【Docker+Nginx+Angular】Dockerfileでイメージ作ってMacでアプリ立ち上げてみた
はじめに
あるプロジェクトで、フロントではAngularを使用していたけど、
ローカルに直にWebサーバーを立ち上げる感じだったので、
Dockerコンテナ上にAngularを入れて、Webサーバー起動できないかなと思い、
挑戦してみました!TL;DR
- 構成の説明
- Angularのローカル上のセットアップ
- Dockerfile解説
- docker-compose.yml解説
- nginx.conf紹介
- 実践とキャプチャ
構成
とりあえず自分は以下のようなディレクトリ構成で進めました。
docker-local ├── .env ├── docker-compose.yml ├── docker │ └── nginx │ ├── Dockerfile │ └── nginx.conf └── web ├── app ── (Angular一式) └── env └── nginx ── site.confAngularのローカル上のセットアップ
Angularに関連するファイル等をDockerコンテナ側にマウントするために、
一旦ローカルで、Angularのセットアップをします。1.
Node.js
のインストールnodejs.orgに行って、
2021/03時点で、LTS(長期サポート)の推奨版14.16.0 LTS
をダウンロード。2.npmの関連ディレクトリのオーナーを自分のアカウントに権限変更
$ npm config get prefix /usr/local $ sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}自分の環境では、アクセス権限エラーが出たので、
/usr/local/bin, /usr/local/share, /usr/local/lib/node_modules
に対してオーナー権限を自分に与えた。3.
angular/cli
のインストールnpm install -g @angular/cli
-g, --global
:グローバルインストール
- npmのインストール場所にパッケージインストール
- つけない場合は、カレントディレクトリのnode_modules内にインストール
4.Angularアプリの作成
$ cd ./web $ ng new app ? Do you want to enforce stricter type checking and stricter bundle budgets in t he workspace? This setting helps improve maintainability and catch bugs ahead of time. For more information, see https://angular.io/strict Yes ? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? Less [ http://lesscss.org
web
のディレクトリに移動してから、angular
アプリをapp
と言う名前で作成。
3つほど、質問されるので、適宜選択。
strict mode
でインストールするかrouting
を追加するかstylesheet
のフォーマットはどうするか5.一応、立ち上げ確認
localhost:4200
上に立ち上がりました!
これで、マウント用のフォルダはOK。
Dockerfile
DockerfileFROM node:14.16.0-alpine3.12 as build-stage WORKDIR /app COPY ./web/app/package*.json /app/ RUN npm install COPY ./web/app/ /app/ ARG configuration=production RUN npm run build -- --output-path=./dist/out --configuration $configuration FROM nginx:1.17.3-alpine COPY --from=build-stage /app/dist/out/ /var/www/html COPY ./docker/nginx/nginx.conf /etc/nginx/解説
ローカル上でやった手順を
Dockerfile
上に書いてあげるイメージです。
linux
はdocker
コンテナに向いている超軽量のalpine
を使用。今回は、マルチステージビルドを利用してます。Dockerfileに複数の
FROM
命令を記述し、異なるベースイメージ使って、それぞれで新しいビルドステージを開始する感じです。
Angualr
のビルド環境としてnode:14.16.0-alpine3.12
をインストール。(build-stage
と名付け)- Angularのビルド生成物を、Nginxのステージでコピーして使ってます。
- docker側のワーキングディレクトリを
/app
に指定- ローカルの
package.json
を/app/
配下にコピー- その
package.json
を使って、npm install
- ローカルのAngularのソースをコピー
- ビルドを走らせて、生成物は
./dist/out
に出力
configuration
はオプションだと思う。nginx
のイメージをインストール- 先述の
Angular
のビルド生成物をDocker
上のNginx
のドキュメントとして扱うため、nginx
のルートディレクトリ/var/www/html
にコピー- Nginx の設定ファイル
nginx.conf
もコピー※ビルドのポイント
docker-compose up
をする前に、docker-compose.yml
がある場所をカレントディレクトリとして、事前にdockerイメージのビルドをしておきます。
理由として、
./web/app/
のファイル等をコピーしたいが、
Dockerfile
は親のディレクトリを参照することができないので、
今回のフォルダ構成的に、コピーすることができず、こういったやり方にしてます。(他にももっと良いやり方あるかも。)# buildコマンド実行場所を docker build のカレントディレクトリにできる $ docker build -f ./docker/nginx/Dockerfile -t image-name:nginx-1.17.3-alpine .※最後のドット . が大事
※buildにcache
使いたくない場合は、--no-cache
つける。
※docker-compose up --build
とかでも良いかもしれないが、自分はまだ試していない、docker-compose
docker-compose.ymlversion: "3.8" services: nginx: image: image-name:nginx-1.17.3-alpine build: context: ./docker/nginx dockerfile: Dockerfile container_name: nginx ports: - 80:80 volumes: - ./web/env/nginx:/etc/nginx/conf.d logging: driver: "none" restart: always※
site.conf
は、docker-compose側でマウントしちゃう感じ。(実際Dockerfile内でもかけるかも)
※image
の設定を、build
した時のイメージ名にすることが大切nginx.conf
※nginxについて内容の精査がまだできていないので、一旦自分のローカルで動いたものの貼り付け。
nginx.conf
内でsite.conf
をincludeする感じ。nginx.confuser nginx; worker_processes 1; 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; include /etc/nginx/conf.d/*.conf; }site.confserver { listen 80; listen 8080; server_name localhost; root /var/www/html; location / { index index.html index.htm; root /var/www/html; try_files $uri $uri/ /index.html =404; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/html/error; } }実際に立ち上がるか確認
コマンドを打ってコンテナ起動・・・
$ cd docker-local $ docker-compose up -d --remove-orphans Creating nginx ... done作成されたのでアクセス!!!
おお、ちゃんと表示された。
localhost:80
で起動してるので、URLをみると:80
が省略されて、
ちゃんとlocalhost
で立ち上がった。デフォルトのままなので、これから何かしらのアプリでも作ってみたいと思いまする。
まとめ
今回の学びは、
マルチステージビルドと
Dockerfileが参照できる範囲
等でした。やっぱりまだまだ、相対パスだったり、マウントの仕方だったりが、なかなか難しいので、
その感覚をもっと養っていけたらと思いました。あとは、
nginx
のconfiguration周りがトーシロ(素人)レベルで全くわかっていないので、
そこら辺を次は追求していきたいなと思ったりしてます。以上、ありがとうございました。
- 投稿日:2021-03-29T10:24:41+09:00
【docker】docker-compose build したらERROR: Service 'web' failed to build : The command '/bin/sh -c bundle install' returned a non-zero code: 7
railsアプリにローカル環境にdockerを導入していました。buildしようと、
docker-compose build
を実行したら、このようなエラーがでました。Your bundle is locked to mimemagic (0.3.5), but that version could not be found in any of the sources listed in your Gemfile. If you haven't changed sources, that means the author of mimemagic (0.3.5) has removed it. You'll need to update your bundle to a version other than mimemagic (0.3.5) that hasn't been removed in order to install. ERROR: Service 'web' failed to build : The command '/bin/sh -c bundle install' returned a non-zero code: 7
どうも、mimemagicというgemが悪さしてそうで、調べてみると0.3.5はyanked(公開停止)されているようでした。
対策
gem mimemagicをアップデートする。
$ bundle update mimemagicちなみにDOCKERFILEはこのように書いていました。
FROM ruby:2.6.6 RUN apt-get update -qq && \ apt-get install -y build-essential \ libpq-dev \ nodejs RUN mkdir /app_name ENV APP_ROOT /app_name WORKDIR $APP_ROOT ADD ./Gemfile $APP_ROOT/Gemfile ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock RUN gem install bundler RUN bundle install ADD . $APP_ROOT参考
- 投稿日:2021-03-29T08:57:35+09:00
ディスクを食い潰す Docker volume の落とし穴
概要
Dockerfile
のVOLUME
は予期せずディスクを食い潰す原因になる- MySQL など多数の公式 Docker イメージで
VOLUME
が使われているため要注意遭遇した問題
ある時、CI サーバーのディスクが圧迫されており、その大部分を Docker volume が占めていることがわかりました。
$ docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 14 5 6.787GB 3.283GB (48%) Containers 8 4 137.5MB 131.4MB (95%) Local Volumes 1281 7 224.8GB 224.3GB (99%) Build Cache 0 0 0B 0B更に詳しく調べてみると、ランダムな名前でほぼ同じ中身の volume が大量に残っていて、無駄にディスク容量を食っているようでした。
$ docker system df -v ... Local Volumes space usage: VOLUME NAME LINKS SIZE 68d96aaf9e8a9098c4ab38c26315f4d25b02b96a51eaf70a7037f655e0dccba4 0 226.6MB cdfb0a70f73d997bf5f7abee7d37adea98891d938da17bda8ae6d25ca5decc71 0 228.6MB f043ee71a3a318ae6479bf0205d3192666ca58b43582572b41046421f502cdef 0 226.6MB 8d15e829f575564683006cb65340687423749fc6b1e52a5fe0e62c81ed40f2e4 0 228.6MB ...問題の原因
ランダムな名前の volume は anonymous volume と呼ばれるもので、以下のような場合に作成されます。
Dockerfile
にVOLUME
指示を書いた場合docker-compose.yml
やdocker run
のオプションで-v /path/in/container
のように指定した場合前述のケースでは CI のテストに Docker を使用し、終了後にコンテナを削除して後始末していたため、
起動時に毎回 anonymous volume が新しく作成され、削除されることも再利用されることもなくゴミとして溜まっていたわけです。一度コンテナから切り離された anonymous volume の出所を特定するのは厄介ですが、
適当なコンテナに volume をアタッチするなどして中身を調べれば手がかりが得られます。$ docker run -it --rm -v <volume の名前>:/volume busybox sh $ ls /volume auto.cnf client-key.pem ibdata1 private_key.pem sys ca-key.pem ib_buffer_pool ibtmp1 public_key.pem ca.pem ib_logfile0 mysql server-cert.pem client-cert.pem ib_logfile1 performance_schema server-key.pem今回 anonymous volume を作り出していた大元の原因箇所は、ベースとして使用する MySQL 公式の Docker イメージの中にありました。
DockerfileVOLUME /var/lib/mysql
Dockerfile
で一度指定されたVOLUME
は、派生イメージやコマンドラインオプションなどで解除できないため、
ベースイメージを使用する全てのユーザーが同様の問題に当たる可能性があります。
これは MySQL 以外にも多くのメジャーな公式イメージで issue として挙がっており、現在でも解決されていません。
- Why is there volume for data in the first place? · Issue #255 · docker-library/mysql
- Volumes should not be defined in base images · Issue #404 · docker-library/postgres
- Volumes should not be defined in base images · Issue #140 · docker-library/redis
- Should not declare VOLUME for /data/db · Issue #306 · docker-library/mongo
- VOLUME declaration can result in difficult to diagnose misbehavior · Issue #410 · docker-library/rabbitmq
対処法
Dockerfile から VOLUME を削除
根本的に volume を作成させないための方法です。
既に述べた通り
Dockerfile
のVOLUME
は解除できないので、イメージの使用方法の選択肢を狭めてしまいます。
volume の設定はDockerfile
の中ではなく、実行時に docker コマンドやdocker-compose.yml
で指定する方が良いでしょう。問題は、 MySQL 公式のイメージなど、管理外の
Dockerfile
でVOLUME
が指定されている場合です。
この場合は自身でレポジトリをフォークしてDockerfile
を書き換える以外に解決策がありません。
しかしこの方法だと、管理すべきコードが増え、フォーク元の変更に追随する手間が発生するためお勧めできません。定期的に volume を掃除
上記の方法が使えない場合、対症療法として volume を定期的に削除する手があります。
docker volume ls -f dangling=true --format "{{ .Name }}" | grep -E '^[a-z0-9]{64}$' | xargs --no-run-if-empty docker volume rm例えばこのコマンドを実行すると、以下の流れで anonymous volume をまとめて削除してくれます。
- 使用されていない volume のリストを取得
- 名前が英数字 64 文字の anonymous volume だけをフィルタ
- 該当する volume を削除
ただし、本当に必要な volume まで削除してしまわないか事前によく確認しておきましょう。
- 投稿日:2021-03-29T06:14:57+09:00
【docker】db:createすると、Plugin caching_sha2_password could not be loaded...のエラーハマった話
背景
railsで作成中のアプリに、開発環境にDockerを導入していました。
DBをcreateしようとするも下記エラー
コンテナのビルドは問題なく出来たので、次にDBを作成するべくこのコマンドを実行したら、下記のエラーに遭遇しました。
$ docker-compose run web bundle exec rake db:create Creating network "golfscore_default" with the default driver Creating golfscore_db_1 ... done Creating golfscore_web_run ... done Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory Couldn't create 'golfscore_development' database. Please check your configuration. rake aborted! Mysql2::Error::ConnectionError: Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory原因と対策
Mysql 8以降、認証プラグインの仕様が変わったためのようです。
ユーザーのプラグインをmysql_native_passwordに変更していきます。docker内のmysqlにログインし、plugin変更
まずはコンテナ内のMysqlにログインするため、コンテナIDを調べます。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bcc91696ca70 mysql:8.0.23 "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 33060/tcp, 0.0.0.0:4306->3306/tcp golfscore_db_1コンテナIDがわかったので、入ります。
$ docker exec -it bcc91696ca70 bash入れました。Mysqlに入ります。
root@bcc91696ca70:/# mysql -uroot -pMysqlのパスワードを入力します。
Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 9 Server version: 8.0.23 MySQL Community Server - GPL Copyright (c) 2000, 2021, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.このコマンドを実行して、現在のプラグインの状況を確認します。
mysql> SELECT user, host, plugin FROM mysql.user;やはり、caching_sha2_passwordになっています。今回はこれが悪さしているようですので、変更していきます。
下記、2コマンド実行して、root user部分の2箇所を変更します。
('password'部分は各自DBのパスワードを入力)mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'; Query OK, 0 rows affected (0.01 sec)mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password'; Query OK, 0 rows affected (0.01 sec)変更できたか確認してみます。
mysql> SELECT user, host, plugin FROM mysql.user;無事、mysql_native_passwordに変更されています。
再度、DBを作成し、無事に成功しました。
$ docker-compose run web bundle exec rake db:create Creating golfscore_web_run ... done Created database 'golfscore_development' Created database 'golfscore_test'参考
- 投稿日:2021-03-29T03:03:45+09:00
ボクとPHP・Laravel・Dockerとの約200時間
始まりは突然に…
あれは、ある企業に面接したときの事でした。それまで、私はRubyでの開発を行っており、ポートフォリオもRailsで作成していました。その面接で、ポートフォリオの説明を行い面接終了時に次のようなお言葉を頂いた時から始まりました。
あなたに課題を出します。それを期限を決めませんが行ってください。とのことでした。課題とは以下の通りです。
それを成し遂げた理由
![]()
それは、至って単純な話です。
やってみたい・挑戦してみたいと思ったかです!
やりたいやってみせるという気持ちで望みました!で、一体何から着手したのか
プロセスは以下の通りです。
①プロゲートの初級(PHP基礎学習)
↓
②ドットインストールPHPに関するもの全て(PHP基礎学習)
↓
③ドットインストールDockerに関するもの全て(Docker基礎学習)
↓
④ドットインストールLaravel基礎の部分のみ(Laravel基礎学習)
↓
⑤Docker環境下でLaravel立ち上げYouTube等の動画を元に実践(Laravel実践学習)
↓
⑥ちょっとした掲示板を作成(Laravel実践学習)
↓
⑦ポートフォリオ作成(ErrorStocker作成)
この様な流れで実施
以下が着手時間です。学習管理に関しては、Studyplusを利用しました。
・PHP基礎学習に費やした時間:31時間11分(2月6日〜2月11日)
・Docker基礎学習に費やした時間:8時間10分(2月7・11・12日)
・Laravel基礎学習に費やした時間:31時間24分(2月11〜18日)
・ErrorStocker作成に費やした時間:130時間4分(2月18日〜3月18日)
合計時間:約200時間?作成したポートフォリオ
題名:ErrorStocker
URL:http://error-st.com
GitHub:https://github.com/miyaseinto/ErrorStokcer何を目的に作成したのか??の前に軸を話させてください!
少し私の話になりますが少々お付き合いください!(どうでもいいんだよテメェの話なんかと思った人は飛ばしてください笑)
これは、私がエンジニアを目指した軸にあります。
【不便に感じたものをデジタル化でより楽ができるように便利に変えたい】これが私がエンジニアを目指した軸です。
なぜその様な軸ができたかというと、前職での公務員経験からこの様な考えが生じたからです。
前職の公務員は超田舎で勤務していました。そのため、デジタル化が都会より著しく劣っており何をするにもアナログで不効率でした。何より住民の方が大変な思いをすることが多々ありました。回覧物だったり、各種手続きだったり、仕方がないことだと考えていました。ですが、エンジニアという職業がそれらを解決に導く職業であるのでは無いかと調べるうちに、それを担ってやりたいという思いが日に日に増していきました。
で、それを勉強したいと思い勉強していく中で自分が書いたコードがブラウザ画面で変化していくことにとてもやりがいを感じ、これを仕事にしたいと考え公務員を退職しエンジニアを目指そうと思い勉強に励みました。
退職した職場には申し訳なかったのですが、自分の腹の中を上司の方々に話すとそれならば挑戦してみろと背中を強く押してくれました。ですので、その思いを全部背負っとるじゃいと思いながらエンジニアになりたいと考えてます。これがエンジニアを目指した軸のお話です。(長々と申し訳ないです笑)作成背景&目的
上記の軸を基に、プログラミングの勉強をしている時に不便に感じたことを便利に変えるために作成しました。
私が、エラーと遭遇した時にリファレンスサイトやQiitaの内容からエラー解決に導こうとします。そこで、いつもは一度エラーした内容をGoogleのブックマークの中にファイルごとに保存して、もう一度確認をしたい時に見直しをしておりました。しかし、情けない話そのファイルをどこに保存したのかがわからなくなり、探すことに時間を掛けることがありました。そこで、検索をかけてその内容を短時間で探せることはできないかと考え作成に至りました。工夫した・苦労したPOINT
・投稿内容をマークダウンで投稿できるようにしたこと(リンクを文字列内に入れたいと考えたため)
・上記と同じだが、コメント機能にもマークダウンを使用したこと(上記と同じ)
・投稿した時間を表記させたこと
・コメントした時間を表記させたこと
・Bootstrapを使用したが、Bootstrap感を排除したこと
・写真の圧縮を行ったこと
・タグを一覧でも表示させたこと
・閲覧用としてログイン簡略化させたこと(通常のログインと表示は異なる)
・ページネーションを導入したこと
・キーワード検索をタイトルの内容と本文の内容で検索できるようにしたこと
・キーワード検索で検索件数を表示させたこと?機能一覧
ユーザー機能
・ユーザー登録(投稿用ログイン)
・ゲストログイン(閲覧用ログイン)
・マイページにて以下の投稿の一覧表示
・自分の投稿内容
投稿機能
・エラーのストックをログインアカウントが投稿・編集・削除
・一覧表示、詳細表示
・投稿一覧表示で10個の投稿数をページネーションを実施
・写真投稿及び圧縮(intervention/image)
・タグ付け(タグ検索)
・キーワード検索(タイトル・内容)
・投稿内容にマークダウンを採用(cebe/markdown)
コメント機能
・投稿にコメントを投稿・編集・削除
・投稿詳細ページにコメント一覧表示
・コメント内容にマークダウンを採用(cebe/markdown)?使用技術
フロントエンド
・HTML / CSS / Bootstrap
バックエンド
・PHP 8.0.2
・Laravel 8.28.1
データベース
・Mysql 8.0
開発環境
・Docker 20.10.2
・docker-compose 1.27.4
本番環境
・AWS(VPC、EC2、S3、Route53)
・Nginx
各種解説内容投稿
- 投稿日:2021-03-29T03:02:31+09:00
Dockerって何からスタート!(自分なりのアウトプット)
Dockerって何??
開発者やシステム管理者が、コンテナでアプリケーションを 構築(build)、実行(run)、共有(share)するためのプラットフォームのことを指します。
イメージとコンテナについて
コンテナとは、ホストマシン(例: 自分のpc)の上に仮想的に利用する箱みたいなもの。ホストマシンとは別の世界を作る感じ。
イメージとは、コンテナの実行に必要な概念としてのパッケージ(ファイルやメタ情報の集合体)である。
参考サイトイメージとコンテナの違いについて
文字より下記の写真の内容のほうがわかるかもです!!
実際のコードを利用して
今回はPHPのDockerファイルとdocker-compose.ymlの情報を解説していきます!
その前にDockerfileとdocker-compose.ymlの違いについて
・Dockerfileには個々のコンテナを構築するために必要な細かい手順(どんなツールをインストールするかなど)を記載する場所
・docker-compose.yamlには個々のコンテナの起動定義(どんな感じで起動していくか)を記載する場所
・要は、Dockerfileは個々のコンテナに関する説明書、docker-compose.ymlはコンテナ全体に関する説明書
コマンド操作については、他の方の投稿内容を参考サイトとして使用します。
Dockerコマンド一覧Dockerfileの記述
info/php/DockerfileFROM php:8.0-fpm-buster #この記述でphp8.0のベースイメージを指定して利用しますよといった命令文 LABEL maintainer="ucan-lab <yes@u-can.pro>" #LABEL命令はイメージに対してメタデータを追加します。 SHELL ["/bin/bash", "-oeux", "pipefail", "-c"] #シェル形式のコマンドに使用 # timezone environment ENV TZ=UTC \ # locale LANG=en_US.UTF-8 \ LANGUAGE=en_US:en \ LC_ALL=en_US.UTF-8 \ # composer environment COMPOSER_ALLOW_SUPERUSER=1 \ COMPOSER_HOME=/composer #ENV命令は環境変数を設定します。 COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer #新しいファイルまたはディレクトリをコンテナのパスにコピーします。--from オプションを付けると別のイメージのファイルを指定できます。(マルチステージビルド)composer のインストールがとてもシンプルになっています。 RUN apt-get update && \ apt-get -y install git libicu-dev libonig-dev libzip-dev unzip locales libfreetype6-dev libjpeg62-turbo-dev libpng-dev && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ locale-gen en_US.UTF-8 && \ localedef -f UTF-8 -i en_US en_US.UTF-8 && \ mkdir /var/run/php-fpm && \ docker-php-ext-install intl pdo_mysql zip bcmath && \ docker-php-ext-configure gd --with-freetype --with-jpeg &&\ composer config -g process-timeout 3600 && \ composer config -g repos.packagist composer https://packagist.org && \ docker-php-ext-install -j$(nproc) gd exif #RUN命令は現在のイメージの上に任意のコマンドを実行した結果をコミットします。Laravelに必要なライブラリー等のインストールを行っています。 COPY ./infra/php/php-fpm.d/zzz-www.conf /usr/local/etc/php-fpm.d/zzz-www.conf COPY ./infra/php/php.ini /usr/local/etc/php/php.ini #ホスト側に置いているPHPの設定ファイルのコピーをしているだけです。 WORKDIR /work/laravel #WORKDIR命令はワークディレクトリを設定します。docker-compose.ymlの記述
app, web, db の3つのコンテナを定義しています。
docker-compose.ymlversion: "3.3" #docker-composeのバージョン volumes: php-fpm-socket: db-store: #名前付きボリューム(ボリュームとは、データを永続化できる場所のことである。外部HDDのようなイメージ。)をマウント(利用できる状態にすること)しています。 #unixソケット(php-fpm-socket)のボリュームは app コンテナと web コンテナで共用したいのでマウントしてます。 #unixソケットとは、まず、ソケットの意味「受け口、接合部」の意味。「UNIXドメインソケット」とは、LinuxなどのUNIX系OS(オペレーティングシステム)で実行されるプロセス間のデータ通信の終点に使われるインターフェースのことをいう。 #データベース(db-store)のデータはコンテナを破棄しても残しておきたいのでボリュームとして定義しています。 services: app: build: context: . dockerfile: ./infra/php/Dockerfile volumes: - php-fpm-socket:/var/run/php-fpm - ./laravel:/work/laravel environment: - DB_CONNECTION=mysql - DB_HOST=db - DB_PORT=3306 - DB_DATABASE=${DB_NAME:-laravel_local} - DB_USERNAME=${DB_USER:-phper} - DB_PASSWORD=${DB_PASS:-secret} #app(アプリケーションサーバ)コンテナの定義です。PHPを実行します。 #build で ./infra/php/Dockerfile を指しています。 #volumes で名前付きボリュームとホストパスをコンテナにマウントしてます。 #../Laravel:/work/backendはLaravelのソースコードをマウントしてます。 #environmentで環境変数を定義している。 web: build: context: . dockerfile: ./infra/nginx/Dockerfile ports: - ${WEB_PORT:-80}:80 volumes: - php-fpm-socket:/var/run/php-fpm - ./laravel:/work/laravel #web(ウェブサーバ)コンテナの定義です。PHP以外の静的コンテンツを返却します。 #ports ポートを公開します。(HOST:CONTAINER) #volumes で名前付きボリュームとホストパスをコンテナにマウントしてます。 #nginxのデフォルトのポート番号は 80 番です。 db: build: context: . dockerfile: ./infra/mysql/Dockerfile ports: - ${DB_PORT:-3306}:3306 volumes: - db-store:/var/lib/mysql environment: - MYSQL_DATABASE=${DB_NAME:-laravel_local} - MYSQL_USER=${DB_USER:-phper} - MYSQL_PASSWORD=${DB_PASS:-secret} - MYSQL_ROOT_PASSWORD=${DB_PASS:-secret} #db(データベース)コンテナの定義です。 #build で ./infra/mysql/Dockerfile を指しています #ports ポートを公開します。 #volumes で名前付きボリュームとホストパスをコンテナにマウントしてます。 #MySQLのデフォルトのポート番号は 3306 番です。 #environmentで環境変数を定義している。参考にしたサイト
この方の内容で解説していただいており、そちらを主に参考に使用しました。
ほとんど、この方の情報を基に書いたので感謝しかないですが、これを自分のものにしていきたいです。