- 投稿日:2020-09-08T23:38:24+09:00
DjangoアプリケーションをDockerコンテナ上で動かす方法(開発および本番環境)
記事の概要
Djangoで作成したWEBアプリケーションを開発・本番環境で動作させる際はいくつかの方法があります。
最近では、Kubernetesが人気となりアプリケーションをコンテナ化する場面も多いです。本記事では開発・本番環境でどのようにDjangoアプリケーションをのせたDockerコンテナを作るかについて記載します。
前提条件・環境
本記事で使用する環境はCentOS7、Docker、Django2系です。
Dockerさえ動けばDockerコンテナは動くため、OSがWindowsでも問題ありません。
開発環境用Dockerコンテナ作成
使用するDockerファイル
開発環境用に使用するDockerファイルは以下になります。
このDockerファイルではdebian:10をベースにして、Pythonをソースコードからインストールしています。
公式PythonのDockerイメージもあるためそちらを使っても問題ないのですが、勉強のためにこのような構成になっています。FROM debian:10 # Install Python3.7.7 WORKDIR /work ADD ./Python-3.7.7.tar.xz . WORKDIR Python-3.7.7 RUN apt-get update && apt-get install -y \ gcc \ libbz2-dev \ libssl-dev \ libffi-dev \ libsqlite3-dev \ make \ tk-dev \ zlib1g-dev \ apache2-dev \ python3-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* RUN ./configure --enable-shared && \ make && \ make install && \ make distclean && \ ./configure && \ make && \ make altbininstall # Install with pip COPY ./requirements.txt . RUN pip3 install --upgrade pip setuptools RUN pip3 install --upgrade wheel RUN pip3 install -r requirements.txt # Deploy App WORKDIR / ADD ./deployfiles.tar.xz . WORKDIR /myapp CMD ["python3", "manage.py", "runserver", "0.0.0.0:80"]Dockerファイルの説明
FROM debian:10まず、Dockerファイルを記載するときはベースとして何を使うか指定します。ここではdebian:10を指定しています。
# Install Python3.7.7 WORKDIR /work ADD ./Python-3.7.7.tar.xz . WORKDIR Python-3.7.7次にPythonのインストールです。
WORKDIRはOSのカレントディレクトリを移動させるような構文です。WORKDIR /workとすればルートディレクトリ(/)直下にworkというディレクトリが作られ(指定したディレクトリがなければ作られます)、そこがカレントディレクトリとなります。
ADDはADD ホストOS上のパス Dockerコンテナ上のパスとすることで指定したホストOS上にあるファイルをDockerコンテナ上のパスへコピー・展開することができます。
ADDはCOPYと異なり、圧縮されたファイルを展開することができます。そのためtarやxzなどのファイルはADDを使ってDockerコンテナ上へコピーすると良いと思います。RUN apt-get update && apt-get install -y \ gcc \ libbz2-dev \ libssl-dev \ libffi-dev \ libsqlite3-dev \ make \ tk-dev \ zlib1g-dev \ apache2-dev \ python3-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*RUNはDockerコンテナ上でコマンドを実行することが出来ます。apt-getを使用し、Pythonのインストールに必要な依存パッケージをインストールしています。
apt-get clean、rm -rf /var/lib/apt/lists/*は不必要なキャッシュやファイルを削除するために実行しています。これを削除することで、作成されるDockerイメージの容量を小さく保てます。
RUN ./configure --enable-shared && \ make && \ make install && \ make distclean && \ ./configure && \ make && \ make altbininstall後は./configure、make、make installです。4行ほど余分なものがありますが、これはエラー対応のためにつけています。
※何らかの組み合わせの問題だとは思うのですが、私が実行したときはこのようにしなければなりませんでした。もしかすると不要かもしれません。
# Install with pip COPY ./requirements.txt . RUN pip3 install --upgrade pip setuptools RUN pip3 install --upgrade wheel RUN pip3 install -r requirements.txtPythonのインストールが終わったら、Pythonパッケージのインストールを行います。ここではpipコマンドを使用してrequirements.txtに記載されているパッケージをインストールします。
COPYはADDと似ていて、COPY ホストOS上のパス Dockerコンテナ上のパスとすることでホストOS上にあるファイルをDockerコンテナ上のパスへコピーできます。こちらは文字通りコピーしかしません。
後はRUNでpipのアップグレードを行い、requirements.txtに基づいてPythonパッケージをインストールします。
# Deploy App WORKDIR / ADD ./deployfiles.tar.xz . WORKDIR /myapp CMD ["python3", "manage.py", "runserver", "0.0.0.0:80"]最後に自分が作ったアプリケーションをDockerコンテナへ加えます。
deployfiles.tar.xzはmyappというディレクトリを圧縮したもので、myapp直下にmanage.pyがあります。
CMDはDockerコンテナが起動するときに実行するコマンドを設定する構文です。これはPythonのリスト形式のように記載でき、各要素は半角スペースで結合されます。つまり、以下のようなコマンドになります。
CMD ["python3", "manage.py", "runserver", "0.0.0.0:80"] ↓ python3 manage.py runserver 0.0.0.0:80Dockerイメージのビルド
Dockerイメージをビルドするには以下のコマンドを実行します。
docker build -t test/myapp .-tオプションはDockerイメージへタグを付けるために使用します。タグを付ければ管理がしやすくなります。
コマンドの最後にはDockerファイルのパスを入れます。ここではカレントディレクトリ(.)を指定しています。
デフォルトではDockerfileという名前のファイルを指定されたパスから探すため、上記で作成したファイル名はDockerfileとしておきます。
作成したイメージを確認するには以下のコマンドを実行します。
docker image lsDockerコンテナの起動
DockerイメージからDockerコンテナを起動するには以下のコマンドを実行します。
docker run --name myapp -d -p 80:80 -v /work/db.sqlite3:/myapp/db.sqlite3 test/myapp:latest--nameオプションはDockerコンテナへ名前をつけます。これは後でこのDockerコンテナを停止、起動、削除したくなったりしたときに便利です。名前は一意なものになるため、名前をつけておけば名前を指定するだけで停止、起動、削除が出来ます。名前がない場合はコンテナIDを指定します。
-dオプションはバックグラウンドでコンテナを実行します。これをつけなかった場合は、Dockerコンテナの標準出力がコンソール上に表示されます。Ctrl + cで抜けられます。ほとんどの場合はバックグラウンドで動かすと思うのでつけておきます。
-pオプションはホストOSのポートとDockerコンテナのポートを紐付けます。ホストOSのポート:Dockerコンテナのポートとします。今回はDjangoのプロセスをDockerコンテナの80番ポートを使用して公開しているため80を指定します。
-vオプションはホストOSのボリューム(DockerボリュームまたはホストOS上のファイルパス)とDockerコンテナのファイルパスを紐付けます。コンテナは終了したときにデータを保持しません。そのため、残しておきたいデータは外部に保管する必要があります。推奨はDockerボリュームですが開発環境のためホスト上OSのファイルパスへデータを保存させます。ここではdb.sqlite3をホストOSからDockerコンテナへ紐付けています。
test/myappは元になるDockerイメージの指定です。latestというのはバージョン名でDockerイメージをビルドしたときに何も指定しなければlatestになります。docker image lsで出力されるTAG列を参照することで確認できます。
正常に起動されているかどうかを確認するには以下のコマンドを実行します。
docker psSTATUS列がUPになっていれば正常に起動しています。
何も出力されない場合は-aをつけて停止中のプロセスも確認します。もしDockerコンテナのログを確認したい場合は以下のコマンドを実行します。
docker logs [コンテナ名またはコンテナID]エラーを確認して対応します。
Djangoアプリケーションへの接続
Dockerを起動しているホストOS上のIPアドレスの公開したポート番号へアクセスします。
本番環境用Dockerコンテナ作成
使用するDockerファイル
本番環境用に使用するDockerファイルは以下になります。
開発環境と違い、python3 manage.py runserverでプロセスを立ち上げるわけにはいきません。Apacheなどの上で動作させるほうが安定します。
ここではベースとしてhttpd:2.4を使用しています。Apache Web サーバの公式Dockerイメージです。
ApacheでDjangoを実行するためにはmod_wsgiというモジュールをApacheへ組み込む必要があります。そのためPython、mod_wsgiをインストールしています。
FROM httpd:2.4 # Install Python3.7.7 WORKDIR /work ADD ./Python-3.7.7.tar.xz . WORKDIR Python-3.7.7 RUN apt-get update && apt-get install -y \ gcc \ libbz2-dev \ libssl-dev \ libffi-dev \ libsqlite3-dev \ make \ tk-dev \ zlib1g-dev \ apache2-dev \ python3-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* RUN ./configure --enable-shared && \ make && \ make install && \ make distclean && \ ./configure && \ make && \ make altbininstall # Install with pip COPY ./requirements.txt . RUN pip3 install --upgrade pip setuptools RUN pip3 install --upgrade wheel RUN pip3 install -r requirements.txt # install ModWsgi WORKDIR /work ADD ./mod_wsgi-4.7.1.tar.gz . WORKDIR mod_wsgi-4.7.1 RUN ./configure \ --with-apxs=/usr/local/apache2/bin/apxs \ --with-python=/usr/local/bin/python3.7 && \ make && \ make install # Set Apache WORKDIR /usr/local/apache2/conf COPY ./httpd.conf . COPY ./server.crt . COPY ./server.key . COPY ./wsgi.conf ./extra COPY ./httpd-ssl.conf ./extraDockerファイルの説明
FROM httpd:2.4ベースとしてhttpd:2.4を指定しています。
# Install Python3.7.7 WORKDIR /work ADD ./Python-3.7.7.tar.xz . WORKDIR Python-3.7.7 RUN apt-get update && apt-get install -y \ gcc \ libbz2-dev \ libssl-dev \ libffi-dev \ libsqlite3-dev \ make \ tk-dev \ zlib1g-dev \ apache2-dev \ python3-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* RUN ./configure --enable-shared && \ make && \ make install && \ make distclean && \ ./configure && \ make && \ make altbininstall開発環境と同様にPythonをインストールします。
# Install with pip COPY ./requirements.txt . RUN pip3 install --upgrade pip setuptools RUN pip3 install --upgrade wheel RUN pip3 install -r requirements.txt開発環境と同様にpipでrequirements.txtに基づいたPythonパッケージをインストールします。
# install ModWsgi WORKDIR /work ADD ./mod_wsgi-4.7.1.tar.gz . WORKDIR mod_wsgi-4.7.1 RUN ./configure \ --with-apxs=/usr/local/apache2/bin/apxs \ --with-python=/usr/local/bin/python3.7 && \ make && \ make installApacheでDjangoを動作させるためにmod_wsgiをインストールします。
# Set Apache WORKDIR /usr/local/apache2/conf COPY ./httpd.conf . COPY ./server.crt . COPY ./server.key . COPY ./wsgi.conf ./extra COPY ./httpd-ssl.conf ./extra最後にApacheの各種configファイル、証明書関連ファイルをコピーします。
Dockerイメージのビルド
開発環境と同様です。
Dockerボリュームの作成
Dockerボリュームを作成するには以下のコマンドを実行します。
docker volume create --name volume-name--nameで指定した名前でDockerボリュームが作成されます。このボリュームはDockerコンテナと紐付けます。
Dockerボリュームの寿命はDockerコンテナと異なります。DockerコンテナがなくなってもDockerボリュームは存在し続けるため、データを永続化できます。
Dockerコンテナの起動
DockerイメージからDockerコンテナを起動するには以下のコマンドを実行します。
docker run --name myapp -d -p 443:443 -v vlume-name:/myapp test/myapp-vオプションだけ開発環境とは異なります。ここではホストOS上のファイルパスではなく、Dockerボリュームを指定しています。volume-nameという名前のDockerボリュームがDockerコンテナ上の/myappと紐付きます。これで/myapp上にあるデータがDockerボリュームへ保存されます。
Djangoアプリケーションへの接続
開発環境と同様です。
使用したソースファイル
- 投稿日:2020-09-08T23:13:47+09:00
udemyの講座でCentOS7を使ってyum -y install dockerした際にCannot find a valid baseurl for repoとエラーが出た場合の対処法
状況
udemy
Linuxコマンドから始めるDocker ~ BE A FIRST PENGUIN AND GROW AS WHALE
https://www.udemy.com/course/linuxdocker-be-a-first-penguin-and-grow-as-whale/learn/lecture/16684274#questions/12224904
セクション3−15にて、CentOSをインストール後
# yum -y install dockerした際に
Cannot find a valid baseurl for repoとエラーが出ました。
CentOSは、そのままインストールしただけではyumコマンドが使えないことがあります。
少なくとも、私が使用したCentOS7.8.2003ではそうでした。環境
macでVirtualBox上にLinux(CentOS7.8.2003)をインストール
rootユーザーで全操作を行ったCentOSをインストール後、dockerをインストールしようとしたらエラーになった
# yum -y install docker1.ONBOOTの記述の変更とDNSの設定をする
以下を開きます。
# vi /etc/sysconfig/network-scripts/ifcfg-??????は
# cd /etc/sysconfig/network-scripts # lsでご自身のディレクトリを確認して入力してください。
私の場合はifcfg-enp0s3とifcfg-enp0s8の二つが存在しましたが、ifcfg-enp0s3のみで行っています。開いた先でONBOOTの記述を"no"から"yes"に変更し、DNSの設定を記述します。
ONBOOT=yes DNS1=8.8.8.8 DNS2=8.8.4.42.再起動
設定が終わったら再起動をします。
# systemctl restart network以上でうまくいかなかった場合はLinuxを再起動してみてください。
3.確認
念の為動作確認をします。
試しにupdateしてみました。# yum update4.Dockerのインストール
# yum -y install dockerもしうまく動かなかったらbaseurlを書き換える
それでも動作が思う通りにならなければbaseurlに問題があるかもしれません。
# vi /etc/yum.repos.d/CentOS-Base.repo全てのbaseurlを以下の記述に変更します。
#baseurl=http://ftp-srv2.kddilabs.jp/Linux/packages/CentOS/7.8.2003/os/x86_64/お使いのバージョンのURLで設定してください。
私は以下のサイトから
https://blog.77jp.net/linux-iso%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8-%E3%81%AE%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%82%B5%E3%82%A4%E3%83%88%E5%9B%BD%E5%86%85%E3%83%9F%E3%83%A9%E3%83%BChttp://ftp-srv2.kddilabs.jp/Linux/packages/CentOS/
を開き
自分のバージョン ➡︎ os/ ➡︎ x86_64/
と開いたURLをbaseurlに設定しています。参考
https://mebee.info/2020/03/21/post-7689/
https://qiita.com/ntkgcj/items/fd8588dcd65a42c34875
- 投稿日:2020-09-08T22:31:22+09:00
DockerでApicurio Studioをホスティングした
Apicurio Studio使ってますか。
私は先日使い始めました。
まだ良くわかっていません。Dockerでホスティングしたのですが、
その道が想像以上に険しかったので、あとに続く人のために遺しておきます。Apicurio Studioとは?
Apicurio Studio(アピクリオ・スタジオ)はApicurioプロジェクトのひとつで、
OSSのOpenAPI設計ツールです。
OpenAPIのツールといえばSwaggerが有名ですが、
複数人で作業するとなると有料プランを利用しないといけません。
Swagger以外にもツールはあるそうですが、結構有料のものばかり(くわしくはこちら)。
業務ならまだしも、趣味開発では支出を避けたいところです。そこで、OSSのApicurio Studioを知りました。
無料というだけでなく、WebのGUIベースの操作で設計できるのも魅力じゃないでしょうか。
モックやテストといった機能はまだなくて後日追加予定らしいですが、タダなら試してみる価値はあると思います。
活発さはぼちぼちです。運用方法
Apicurio Studioを使うには次の3つの方法があります。
- 公式がお試し用として配信しているLiveバージョンを使う
- ローカルマシンでホスティングする
- Dockerでホスティングする
2はダウンロードしてすぐ使えるスクリプト込の「クイックスタート」が楽だと思います。
3もdocker-composeを簡単に実行できるスクリプトがGitHubにあります。本格運用するなら2か3でしょうが、私はサーバー群をdocker-composeで運用しているので、Apicurio StudioもDockerで立てようと思います。
さらに、上記で述べたGitHubで公開されているスクリプトではDBやらURLの融通が聞かないので、自前でやろうと思います。ちなみに、公式ドキュメントはあまり親切ではありません。
Dockerイメージのページにある説明も簡素なもので、結構試行錯誤しました。
現状動いているので大丈夫だとは思いますが、なにか間違っていればコメントでご指摘いただけると幸いです。アーキテクチャ
Apicurio StudioをDockerで運用するには、アーキテクチャの理解が不可欠です。
1サービスとは思えない構造で、4つのイメージから成っています。図はOpenShiftと書いてありますが、Dockerでも同じです。
図内の表記 イメージ名 役割 Angular based UI application, Apicurio Studio UI Component apicurio-studio-ui フロントエンド Apicurio Studio API Component apicurio-studio-api バックエンド Apicurio Studio WebSocket Component apicurio-studio-ws 編集画面の同期用WebSocket KEYCLOAK apicurio-studio-auth ユーザー認証 この構成にならってもいいんですが、
この中のapicurio-studio-authはDBがH2限定なんで、KEYCLOAKは別途イメージから作ろうと思います。
よって、今回作るのは以下のような構成になります。
イメージ コンテナ名 postgres pg nginx deploy jboss/keycloak keycloak apicurio/apicurio-studio-ui apicurio-ui apicurio/apicurio-studio-api apicurio-api apicurio/apicurio-studio-ws apicurio-ws ドメインはこの記事ではexample.comとします。
docker-composeの設定
以下のdocker-compose.ymlファイルでコンテナを起動します。
起動時にDBの初期化があるので、pgを先に起動し、設定したあとで他のコンテナを起動します。docker-compose.ymlversion: '3' services: pg: image: postgres restart: always environment: POSTGRES_USER: xxxx POSTGRES_PASSWORD: xxxxxx volumes: 略 deploy: image: nginx restart: always ports: - 80:80 - 443:443 volumes: 略 keycloak: image: jboss/keycloak restart: always environment: DB_VENDOR: postgres DB_ADDR: pg DB_PORT: 5432 DB_DATABASE: keycloak DB_USER: xxxx DB_PASSWORD: xxxxxx KEYCLOAK_USER: admin KEYCLOAK_PASSWORD: XXXXXX volumes: 略 apicurio-api: image: apicurio/apicurio-studio-api restart: always environment: APICURIO_KC_AUTH_URL: https://keycloak.example.com/auth/ APICURIO_HUB_STORAGE_JDBC_TYPE: postgresql9 APICURIO_DB_DRIVER_NAME: postgresql APICURIO_DB_CONNECTION_URL: jdbc:postgresql://pg:5432/apicurio APICURIO_DB_USER_NAME: xxxx APICURIO_DB_PASSWORD: xxxxxx APICURIO_DB_INITIALIZE: "true" APICURIO_HUB_STORAGE_JDBC_INIT: "true" depends_on: - pg - apicurio-ws apicurio-ws: image: apicurio/apicurio-studio-ws restart: always environment: APICURIO_KC_AUTH_URL: https://keycloak.example.com/auth/ APICURIO_HUB_STORAGE_JDBC_TYPE: postgresql9 APICURIO_DB_DRIVER_NAME: postgresql APICURIO_DB_CONNECTION_URL: jdbc:postgresql://pg:5432/apicurio APICURIO_DB_USER_NAME: xxxx APICURIO_DB_PASSWORD: xxxxxx APICURIO_DB_INITIALIZE: "true" APICURIO_HUB_STORAGE_JDBC_INIT: "true" depends_on: - pg apicurio-ui: image: apicurio/apicurio-studio-ui restart: always environment: APICURIO_KC_AUTH_URL: https://keycloak.example.com/auth/ APICURIO_UI_HUB_API_URL: https://apicurio-api.example.com APICURIO_UI_EDITING_URL: wss://apicurio-ws.example.com depends_on: - pg - apicurio-api - apicurio-wspostgreSQLの設定
keycloakとApicurio Studioで使うデータベースを作成しておきます。
データベースの作成create database keycloak; create database apicurio;nginxの設定
Apicurio StudioはJavaScriptでAPIやWebSocketにアクセスするので、
複数のコンテナすべてのポートをホストのポートとバインドする必要があります。
でもそんなにいくつもポートを使っていると、何番が何だったとか、ポートフォワーディングの設定が大変なので、
リバースプロキシを挟んで起きます。
nginxコンテナの80と443だけをホストとバインドし、すべてのWeb通信はnginxを通します。リバースプロキシを設定して、docker-compose.yml内に記述したURLでそれぞれアクセスできるようにします。
※常時SSL設定などは省略しています。nginx_apicurio.conf# keycloak server { listen 443 ssl; listen [::]:443 ssl; server_name keycloak.example.com; location / { include /etc/nginx/params/proxy_params; proxy_pass https://keycloak:8443; } } # ui server { listen 443 ssl; listen [::]:443 ssl; server_name apicurio.example.com; location / { include /etc/nginx/params/proxy_params; proxy_pass http://apicurio-ui:8080; } location /studio { return 301 https://$host; } } # api server { listen 443 ssl; listen [::]:443 ssl; server_name apicurio-api.example.com; location / { include /etc/nginx/params/proxy_params; proxy_pass http://apicurio-api:8080; } } # ws server { listen 443 ssl; listen [::]:443 ssl; server_name apicurio-ws.example.com; location / { include /etc/nginx/params/proxy_params; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://apicurio-ws:8080; } }Keycloakの設定
Keycloakはシングルサインオンを提供するOSSです。
予めアプリケーションを登録しておき、
アプリケーションからKeycloakにリダイレクト、認証したらKeycloakからアプリケーションにリダイレクトすることで、ログイン情報を認証します。Keycloakにアプリケーションを登録するには、realmと呼ばれるプロジェクトのようなもの、clientと呼ばれるアプリケーションを作成する必要があります。
設定項目が多くて大変なので、設定済みのものを拝借しましょう。apicurio-studio-authからの設定エクスポート
上記apicurio-studio-authイメージには諸々設定済みのKeycloakが用意されています。
なので、apicurio-studio-authイメージでコンテナを起動し、Apicurioのrealm情報をエクスポートし、今回用意したKeycloakにインポートすればいいです。まずはコンテナを起動します。
8080ポートに接続できるようにし、管理画面へのログイン情報を環境変数で渡しておきます。コンテナの起動docker run -it -p 8080:8080 \ -e "APICURIO_KEYCLOAK_USER=admin" \ -e "APICURIO_KEYCLOAK_PASSWORD=admin" \ -e "APICURIO_UI_URL=https://apicurio.example.com/" \ apicurio/apicurio-studio-auth起動したら、ブラウザで
http://localhost:8080/auth/にアクセスしてログインします。
上記コマンドで起動した場合、ID:admin、password:adminでログインします。
左上でApicurioが選択されていることを確認し、最下部のExportをクリックします。
(一応)2つの項目をONにし、Exportを押します。
しばらくするとjsonファイルがダウンロードできます。
realmのインポート
先程ダウンロードしたjsonを今回用意するKeycloakにインポートします。
コンテナが起動したら、ブラウザでhttps://keycloak.example.com/auth/にアクセスし、ログインします。「Master」というデフォルトのrealmが選択されているはずなので、「Add realm」から先程のjsonをインポートします。
ログインできるよう設定
ログインページの形式を決めます。
設定完了(のはず)
https://apicurio.example.comにアクセスすると、ログイン画面が表示されます。
ユーザー登録をするとログインできます。
APIの追加、編集をしてみて、動けば成功です。
失敗しててもめげずに、あれこれいじってみてください。
ブラウザのコンソール、各コンテナのログを見れば解決できると思います。間違えても簡単にやり直せます。Dockerならね。
- 投稿日:2020-09-08T21:58:57+09:00
rails + mysql5.7で"Mysql2::Error: Expression #1 of ORDER BY clause is not in SELECT list, references column 'テーブル名.カラム名' which is not in SELECT list "
環境
ruby 2.5.1
rails 5.2.4
mysql 5.7背景
railsのDBをmysqlに変えて、rspecを実行したら、見慣れぬエラーが発生
ActionView::Template::Error: Mysql2::Error: Expression #1 of ORDER BY clause is not in SELECT list, references column 'portfolio1_test.users.name' which is not in SELECT list; this is incompatible with DISTINCT: SELECT DISTINCT `communities`.* FROM `communities` LEFT OUTER JOIN `community_users` ON `community_users`.`community_id` = `communities`.`id` LEFT OUTER JOIN `users` ON `users`.`id` = `community_users`.`user_id` ORDER BY `users`.`name` DESC, created_at DESC LIMIT 15 OFFSET 0原因
Mysqlから以下の設定が追加されたために問題が発生していたらしい
sql_mode,'ONLY_FULL_GROUP_BY解決策1
上記の設定が影響するSQL文を変える
MySQL5.7にアップデートしたらonly_full_group_byでエラーになった解決策2
Mysqlの設定を変える
Ransack の sort_link が MySQL で動作しない( incompatible with DISTINCT)今回はMysqlの設定を変えることにした
変更する箇所が多すぎるので、Mysql の設定を変えることにした。
ローカルでは設定を変えることで、問題が解決するが、Docker 環境でもこの設定変更を実行させたい。docker-compose.yml にて command を使って、設定を変更できるはず。
コンテナを構築する際に、Mysqlの設定を反映させたい
MySQL 5.7 のONLY_FULL_GROUP_BY が出た時にDockerでやった対処
docker-compose.ymlversion: '3' services: web: build: context: . dockerfile: Dockerfile command: bundle exec rails s -p 3000 -b '0.0.0.0' tty: true stdin_open: true depends_on: - db ports: - "3000:3000" volumes: - .:/myapp:delegated db: image: mysql:5.7 command: - --sql-mode=NO_ENGINE_SUBSTITUTION #追加!! environment: MYSQL_USER: root MYSQL_ROOT_PASSWORD: password ports: - '3316:3306' volumes: - ./db/mysql/volumes:/var/lib/mysql
- 投稿日:2020-09-08T21:27:04+09:00
Dockerを使ったデータ解析環境の構築(個人的備忘録)
Dockerfileの作成
DockerfileFROM ubuntu:latest # -yはインストールの際全てyesで答え、インストールする RUN apt-get update && apt-get install -y \ # ubuntu上でroot以外のユーザーがroot権限でコマンドを打ちたい時に使用 sudo \ # httpを使ってデータをダウンロードする wget \ # エディター vim # anacondaのインストローラの保存場所 WORKDIR /opt # anacondaのインストローラをダウンロードする。 RUN wget https://repo.continuum.io/archive/Anaconda3-2019.10-Linux-x86_64.shapt-getはubuntuのパッケージ管理ツールで、「\」区切りでパッケージを分けて記述すると、何がインストールされているのかが分かり易い
Dockerfileでコンテナのビルド
-#これでubuntuのパッケージと、optディレクトリの中にanacondaのインストローラがダウンロードされる。 % docker build . -# 作成したコンテナの起動 % docker run -it コンテナID bash -# optになっているのは「WORKDIR /opt」の指定があるため -# インストローラがあることを確認する。 root@85a5e79aa6c2:/opt# ls Anaconda3-2019.10-Linux-x86_64.sh -# インストローラの実行 # sh Anaconda3-2019.10-Linux-x86_64.sh1.エンターを押し続ける
2.yesと答える
3.どこにインストールするか聞かれるので/opt/anaconda3とする
4.init(初期化)するか聞かれるので、yesと答える
5.「Thank you for installing Anaconda3!」と表示されたらダウンロードされている。
しかしながらパスを通していないため、「python」は使えない。パスを通すとは
環境変数$PATHに、パスを追加することでコンピュータがプログラムをそのパスから探してきてくれる。
環境変数の確認
# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binpythonを探す
-# 「anaconda3」ディレクトリに移動 # cd anaconda3 -# 「bin」ディレクトリに移動 # cd bin -# 「python」の起動 # ./python -# パスの確認 # pwdPythonが起動したのが確認できる。つまりパスを通すとは「/opt/anaconda3/bin」を通す。
パスを通す
-# pythonから出る。 >>> exit() -# パスの追加(=の両隣に半角スペースは無し) # Export PATH=/opt/anaconda3/bin:$PATH -# パスの確認 # echo $PATH -#/opt/anaconda3/binが追加されていることがわかる。 /opt/anaconda3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin -# 「opt」に移動 # cd /opt -# pythonの起動確認 # pythonパスを通したことにより、Pythonが「opt」ディレクトリでも起動したことがわかる。
インストローラのオプションの確認
-# sh -x インストローラのファイル # sh -x Anaconda3-2019.10-Linux-x86_64.shAnaconda2-2019.10-Linux-x86_64.shに使えるオプションが表示され今回は-bと-pを使う。
-bはバッチモードで起動。Dockerfileで使う場合に使用。インタラクティブな操作を回避する。
-pはデフォルトは「/root/anaconda3」で、指定することで任意の場所にインストールできる。
再度「anaconda3」を消してインストールできるか確認する。-# anaconda3の削除 # rm -r anaconda3/ -# インストローラからダウンロード及びoptディレクトリ内にanaconda3の作成 # sh Anaconda3-2019.10-Linux-x86_64.sh -d -p /opt/anaconda3異常なくダウンロードされたことが確認できる。
Dockerfileの更新
DockerfileFROM ubuntu:latest RUN apt-get update && apt-get install -y \ sudo \ wget \ vim WORKDIR /opt #------------ここから変更------------# RUN wget https://repo.continuum.io/archive/Anaconda3-2019.10-Linux-x86_64.sh && \ # インストローラからダウンロード及びoptディレクトリ内にanaconda3の作成 sh https://repo.continuum.io/archive/Anaconda3-2019.10-Linux-x86_64.sh -b -p /opt/anaconda3 && \ # インストローラーの削除 rm -f Anaconda3-2019.10-Linux-x86_64.sh # パスを通す$PATHは自己参照 ENV PATH /opt/anaconda3/bin:$PATH # 「pip」はpythonのパッケージを管理するツール RUN pip install --upgrade pip CMD [ "jupyter","lab","--ip=0.0.0.0","--allow-root","--LabApp.token=''" ]Dockerfileでコンテナのビルド
% docker build . % docker run -p 8888:8888 作成したコンテナIDこれでコンテナにjupyterlabが立ち上がり、localhost:8888で接続できることが確認できる。
ファイルシステムの共有
-# どこでもいいので共有するファイルを作成する % mkdir ds_python -# 共有するファイルのパスの確認 % pwd -# コンテナの共有ファイルは今回は「work」ディレクトリとする。コンテナ名は「my-lab」 % docker run -p 8888:8888 -v 共有するファイルのパス:/work --name my-lab 作成したimage名localhost:8888で確認し、「work」ディレクトリが作成されていることを確認する。
jupyterlabでworkディレクトリで何かしらファイルを作成し、ホスト側の「ds_python」ファイルの中身を確認し、jupyterlabで作成したファイルが存在していることを確認する。
- 投稿日:2020-09-08T20:01:26+09:00
ERROR: In file ./.env: environment variable name 'THOR_SILENCE_DEPRECATION ' may not contain whitespace. への対処法
タイトルの通りですが、今回は
.envERROR: In file ./.env: environment variable name 'THOR_SILENCE_DEPRECATION ' may not contain whitespace.というエラーが出た際の対処法について、私の環境下でのソリューションを共有したいと思います。
私はRuby on Railsでプログラミング学習を開始して1ヶ月ほどの初学者ですので、至らない点や説明不足の点等もあるかと思います。
お気づきの点等ございましたらご指摘いただけると幸いです。※できるだけ初学者の方にも分かりやすく説明する事を心がけているため、やや冗長に感じる部分もあるかもしれませんがご了承くださいませ。
環境
・Ruby 2.6.5
・Rails 5.2.3
・MySQL 5.7
・Docker
・Dokcer-compose version: '3'まずは解決した方法から
早速ですが解決方法から述べたいと思います。
私の環境下では、ルートディレクトリ
(DockerfileやGemfile等のファイルと同じ階層)
に存在する.envファイルの記述が間違っていた事が原因でした。.env#こちらがエラーが出てしまう記述 THOR_SILENCE_DEPRECATION = true #以下の記述に修正すればエラーは解消される THOR_SILENCE_DEPRECATION=trueエラーが出てしまう記述では、余計な空白が入ってしまっていますね。
空白を除去する事で、上記エラーは解消されます。エラーの深掘り
エラーの内容を再度見てみましょう。
.envERROR: In file ./.env: environment variable name 'THOR_SILENCE_DEPRECATION ' may not contain whitespace.こちらの文章をGoogle翻訳で日本語に修正してみると、
エラー:ファイル./.env:環境変数名 'THOR_SILENCE_DEPRECATION'に空白が含まれていない可能性があります。
と変換されます。
日本語としては若干分かりづらいのですが、なんとなく
「空白の関係でエラーが出ているのだな」
とアタリをつける事ができます。
エラー文本文でググってみると、完全に同じエラー文が出てきた方はいらっしゃいませんでしたが、解決にあたっては以下のブログを参考にさせていただきました。
Composerで.env内のスペースはクォートで囲む必要があるエラーが発生
https://awesome-linus.com/2019/04/07/composer-install-error-need-quotes/エラー文でググったところ情報が少なかったため、おそらくそう頻繁に出るエラーではないのだと予測できますが、初学者の方がエラーに遭遇した際の一つのソリューションとして参考になれば幸いです。
エラーが起きた背景を詳しく
エラーが起きた背景について、もう少し詳しく記述していきます。
このエラーは「.envファイル」の記述が間違えているのが原因なのですが、そもそも.envファイルを触った事がないという方もいらっしゃるかも知れません。
私も約1ヶ月ほどRailsを勉強してきた中で、.envファイルを触る機会というのは一度もなかったのですが、ログイン機能を実装するGem「sorcery」を導入する過程で、以下のエラーを解決するために.envファイルを触る必要が出てきました。
Deprecation warning: Expected string default value for '--test-framework'; got false (boolean). This will be rejected in the future unless you explicitly pass the options `check_default_type: false` or call `allow_incompatible_default_type!` in your code You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.こちらのエラーは、
・Gemfileにsorceryを追加
・bundle install
・sorceryを使用するためのコマンド「rails g sorcery:install」を実行という過程の中で発生したものです。
エラーの詳細については私もよく分かってはいないのですが、どうやらシェルスクリプトを生成するためのGemからエラーが出ているらしいとのこと。
このエラーを解決するための方法として、.envファイルに
.env#正しい記述 THOR_SILENCE_DEPRECATION=trueの記述を追加する必要があり、
誤って以下のコードを記述。.env#不要な空白があるためエラーが出る記述 THOR_SILENCE_DEPRECATION = trueそして、rails g controller ~~
を実行しようとしたところ、タイトルのエラーが発生したという経緯です。ちなみに、「Deprecation warning〜〜〜」のエラーに関しては、以下の記事
[Ruby on Rails]環境変数の設定方法(.bash_profile、Dotenv-rails)
https://qiita.com/yuichir43705457/items/7cfcae6546876086b849RSpecを導入する
https://qiita.com/d0ne1s/items/1ecd114b33e80058215fを参考に解決する事ができました。
ありがとうございました。おしまい
以上が、今回のエラーの解決方法と周辺情報です。
あまり情報が多くないエラーでしたので、もし遭遇して困っている方は参考にしていただけると幸いです。
また、説明が分かりづらい点等があれば、ご指摘いただければと思います。それでは、最後までお付き合いいただきありがとうございました。
- 投稿日:2020-09-08T17:10:42+09:00
FluxでGitOpsフローを構築してリリースした話
どういう話
先日リリースされたサービスで、自分がインフラとそれに付随するデプロイフローを構築したので、その備忘録。
あと、k8s周りを調べるとハンズオンが結構多かった印象だったので、実際にリリースまでしたものをアウトプットしたかった。
前提
Fargateを利用していますが、Fargate特有の話はあまりないです。
アプリケーションコードはGitHub, インフラコードはCodeCommitで管理しています。※インフラコードをCodeCommitで管理している理由は、コード上に時々必要になる12桁のAWSIDは秘匿情報と考えており、
これを(privateとはいえ)GitHub上のリポジトリで管理するのは得策ではないと考えたためです。
CodeCommit上であれば、そもそもCodeCommitにアクセスするのにAWSの認証が必要なので安全であると考えています。
Fargateでは当時kubernetes-external-secretsなどを使うことができなかったための苦肉の策です。出てくるもの
Flux GitOpsフローを構築するのに使っています(メインの話)
FluxCloud FluxからのイベントをキャッチしSlackに通知するためにつかってますGitOpsって何?
WeaveWorksが提唱するデプロイフローです。
Guide To GitOps
コマンドラインツールを用いずにCI/CDを行うGitOpsとは?
超絶簡単に言うと、"全ての変更はGit上のコードとして履歴が管理される"フローです。
デプロイフロー
メインの話です。
GitOpsを提唱しているWeaveWorksが開発しているFluxを用いたフローを構築しました。アプリケーションコードの場合
- githubにアプリケーションコードをcommitする
- CicleCIがECRにイメージをpush
- イメージのpushを検知したfluxがCodeCommit上のmanifestファイルを更新してcommit
- 更新されたmanifestファイルを元にfluxがk8sクラスターを更新する
インフラ(k8s)コードの場合
- CodeCommitにcommitする
- commitをfluxが検知し、manifestファイルを元にk8sクラスターを更新する
Flux設定
Fluxのdeployment.ymlは最初から色々なものが書かれていますが、触ったところは大きく2つです。
- gitリポジトリとECR設定deployment.ymlargs: - --git-url=ssh://********************@git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/********* - --git-branch=master - --git-path=k8s/production - --git-label=flux - --git-user=flux - --git-email=flux@example.com - --registry-ecr-region=ap-northeast-1 - --registry-ecr-exclude-id=[]
- fluxcloud設定deployment.ymlargs: - --connect=ws://fluxcloud
デプロイ方法
staging
developブランチにpushされると自動でstaging環境にデプロイされます。
config.ymlregister_staging_image: jobs: - aws-ecr/build-and-push-image: executor: name: aws-ecr/default use-docker-layer-caching: true account-url: ECR_URL create-repo: false dockerfile: .dockerenv/Dockerfile.production path: . region: AWS_DEFAULT_REGION repo: STG_REPO_NAME tag: "${CIRCLE_SHA1}" filters: branches: only: developproduction
github上でmasterブランチに対してリリースタグを打つとproduction環境にデプロイされます。
リリースバージョンは1.0.0や1.0.0.0.1など、数字とピリオドの組み合わせのみにしてあります。
config.ymlregister_production_image: jobs: - aws-ecr/build-and-push-image: executor: name: aws-ecr/default use-docker-layer-caching: true account-url: ECR_URL create-repo: false dockerfile: .dockerenv/Dockerfile.production path: . region: AWS_DEFAULT_REGION repo: PRD_REPO_NAME tag: "${CIRCLE_TAG}" filters: branches: ignore: /.*/ tags: only: /[0-9]+(\.[0-9]+)+/ロールバック
FluxがcodeCommit上の変更を検知してk8sクラスターを更新してくれるので、
codeCommit上で目当てのバージョンまでrevertするか、イメージタグを変更してcommitすると変更できます。デプロイ通知
FluxCloudを用いてwebhookを通じてSlackにデプロイ通知を送信しています。
deployment.yml- name: SLACK_URL value: "https://hooks.slack.com/services/******/**********/**************" - name: SLACK_CHANNEL value: "channel" - name: SLACK_USERNAME value: "Production Deployment" - name: SLACK_ICON_EMOJI value: ":kyaru-chan:" - name: GITHUB_URL value: "https://ap-northeast-1.console.aws.amazon.com/codesuite/codecommit/repositories/**********"総括
少し前まではcapistranoなどを使って手作業でデプロイしていたので、相当楽で便利になりました。
このフローを最初に作ってしまえばエンジニアは開発に集中できるし、デザイナーやコーダーといった方のコミットでも自動でstagingにデプロイされるので、ある意味エンジニアを開放しているのかもしれないです。アプリケーション周りも頑張ったのでそっちも書くかもしれません
- 投稿日:2020-09-08T17:03:16+09:00
GitHub ActionsでDockerコンテナをGitHub Package RegistryやDocker Hubにpushした話
この記事はお試しで 自分のブログ と同じ内容を投稿しています。
GitHub ActionsでDockerコンテナをGitHub Package Registryにpushした話をしようと思います。
想定読者
- dockerのビルドがなんとなくわかる
背景
現在私は会社のベースイメージとして使えるように
https://github.com/fagai/docker-php
というgithubリポジトリでDocker Hubにautomated buildを設定してDocker Hubからビルドを行っていました。
Docker Hubのビルドタイムラインは非常に遅くて、ちょいちょいストレスになりつつもなんとか続けていました。ただ、最近になってDocker Hubのpull制限だったりとか、GitHubがContainer Registryがパブリックベータになったりしてどうにかしたいなぁと思いまして、GitHub ActionsでBuild+Pushすることにしました。
GitHub Container Registry(GCR)とGitHub Package Registry(GPR)は違う
ここから、GitHub Container RegistryをGCRと省略します、決してGoogle Container Registryではないですので注意してください。(略が被るの困るね)
前者は先日パブリックベータとして出たほうで、後者は少し前からあったものです。
2つの違いは
- URLが異なる(ghcr.ioとdocker.pkg.github.com)
- ユーザ(or Organization)に紐づくか、Repositoryに紐づくかが違う
といったところです。
紐づく部分に関してはURLのパスも以下のように違います。
- ghcr.io/OWNER/IMAGE_NAME
- docker.pkg.github.com/OWNER/REPOSITORY/IMAGE_NAME
こんな感じでユーザに紐づくかリポジトリに紐づくか違います。
まあ、以下に書いていく内容はどちらでも同じように書くことが可能なので、Package Registryなんだ・・・ってなっても見ると良いと思います。もともと私はGitHub Container Registryを使おうとしてましたが、ドメインがghcr.ioとなっておりなんだろうこれ・・・GitHubじゃないんじゃね・・・?とか思っちゃってGitHub Package Registryを使いだした次第です。
現状で言えばGCRのほうがmanifestのバージョンが新しかったりして使う分にはGCRのほうがいいと思います。パッケージに紐付けたいときはGPRを利用しましょう。最初やったとき
最初はstarter-workflowのdocker publishを使ってました。
https://github.com/actions/starter-workflows/blob/master/ci/docker-publish.yml
DockerHubと比べてQueueに積まれる時間もないのでめちゃくちゃ良かったです。
次第に
次第にDockerHubにもpushできないかと思って、探した結果 https://github.com/docker/build-push-action を見つけてこちらに書き換えることに。
https://github.com/docker/build-push-action
- name: Push to GitHub Packages uses: docker/build-push-action@v1 with: dockerfile: ${{ matrix.images }}/Dockerfile username: ${{ github.actor }} password: ${{ secrets.CR_PAT }} registry: docker.pkg.github.com repository: fagai/docker-php/${{ env.IMAGE_NAME }} tags: ${{ env.IMAGE_VERSION }}スリム~~。
CR_PATの箇所ですが、Container Registry Personal Access Tokenとかの略なんでしょうか、実はstarter-workflowのときにそう書いてあったのでその名前でgithubのtokenをセットしました。(github.tokenでも良いのですが、access tokenをできる限り絞ったほうが良いらしくaccess repositoryとwrite repositoryだけの権限をつけました)後にDocker Hubのpushの設定もつけました。
- name: Push to Docker Hub uses: docker/build-push-action@v1 with: dockerfile: ${{ matrix.images }}/Dockerfile username: ${{ github.actor }} password: ${{ secrets.DOCKER_HUB_TOKEN }} repository: fagai/${{ env.IMAGE_NAME }} tags: ${{ env.IMAGE_VERSION }}build-push-actionの例ではpasswordを設定するようになっていましたが、Docker Hubにもaccess tokenがあるのでそっちを設定してからつけました。
https://docs.docker.com/docker-hub/access-tokens/
キャッシュとか色々ちゃんとしたい
現状のままではキャッシュを参考にしてくれません。(ただ、2回目のbuild-push-actionはcacheを元にしてくれるので片方でbuild+pushしてしまえばもう片方はすぐにpush出来ます)
build-push-actionに
cache_fromsというパラメータがあるのでこれをうまく使いたいです。色々試していく結果、
cache_fromsを利用するためにはBuildkitを使う必要があることがわかりました。
また、build_args: BUILDKIT_INLINE_CACHE=1をセットしないといけないことも判明。
どうやらcache_fromsはドメイン部分も指定しないとダメっぽい雰囲気でした。←ここ結構悩んだということでこんな感じになりました。
- name: Push to GitHub Packages uses: docker/build-push-action@v1 env: DOCKER_BUILDKIT: 1 with: dockerfile: ${{ matrix.images }}/Dockerfile username: ${{ github.actor }} password: ${{ secrets.CR_PAT }} registry: docker.pkg.github.com repository: fagai/docker-php/${{ env.IMAGE_NAME }} tags: ${{ env.IMAGE_VERSION }} build_args: BUILDKIT_INLINE_CACHE=1 cache_froms: docker.pkg.github.com/fagai/docker-php/${{ env.IMAGE_NAME }}:${{ env.IMAGE_VERSION }}これで行ける!と思ったのですが
キャッシュされてない・・・となりまして、Actionsのほうを見てみると
#4 importing cache manifest from docker.pkg.github.com/fagai/docker-php/php... #4 ERROR: httpReaderSeeker: failed open: could not fetch content descriptor sha256:65d9f276544048f140bb1a1cceea52f86e7e704b351c56b8d6b9f18c5e9c0e4d (application/vnd.docker.distribution.manifest.v2+json) from remote: not foundこんな感じでエラーが出てキャッシュが取得できずにそのままビルドが走ってしまっていました。
どうやらGitHub Package Registryのほうはdockerの新しいmanifestにまだ対応してないようです。(GitHub Container Registryのほうは対応している様子)https://github.community/t/handle-multi-arch-docker-images-on-github-package-registry/14314
ということで、先にdocker Hubの方からビルドすることにしました。
cache_fromsはdocker.ioから書かないとダメです。- name: Push to Docker Hub uses: docker/build-push-action@v1 env: DOCKER_BUILDKIT: 1 with: dockerfile: ${{ matrix.images }}/Dockerfile username: ${{ github.actor }} password: ${{ secrets.DOCKER_HUB_TOKEN }} repository: fagai/${{ env.IMAGE_NAME }} tags: ${{ env.IMAGE_VERSION }} build_args: BUILDKIT_INLINE_CACHE=1 cache_froms: docker.io/fagai/${{ env.IMAGE_NAME }}:${{ env.IMAGE_VERSION }}ということでこんな感じになります。
#4 importing cache manifest from docker.io/fagai/php:7.2-alpine-fpm #4 DONE 0.2sその後の処理もCACHEDという表示がされ、ビルドが動かずにキャッシュをベースにしていることがわかります。
その後の後付け
- name: cancel old workflow uses: styfle/cancel-workflow-action@0.4.1 with: access_token: ${{ github.token }}これは過去にやったことがありました。過去のActionをキャンセルしてくれるActionです。
何度もcommitしたときに過去のActionがずっと残って動いてしまうことを解決してくれます。また、scheduleもセットしまして、毎週月曜日にActionが動くようにしました。
on: push: branches: - master pull_request: # 定期更新をやる(毎週月曜日) schedule: - cron: '0 0 * * 1'最後に
GitHub Actionsにbuildとpushをするようにした結果、Docker HubがずっとQueueで待ちになる問題も解決されたし、何より並列でビルドができるので短時間でpushするように出来ました。
build-push-actionはv2でbuildxというDocker 19.03で新しく追加されたビルドが利用されるようになるみたいです。
BuildKitは半公式みたいな感じでBuildxが公式のマルチCPUビルド対応の機能みたいです。
macとかではdocker buildx installと打つことでdocker buildへのエイリアスが貼られて勝手にbuildxを使ってくれるようになります。いいね。
- 投稿日:2020-09-08T14:42:52+09:00
kintoneクローン? OSSWebDBのExmentをLightsail+Dockerで立ち上げたら結構ハマったのでメモしておく
Exment is 何?
Exmentは、Laravel製(ということは、LAMPですね)のWeb DBシステムです。リレーショナルなデータベースをGUI管理画面から操作できます。ExmentはOSSで、GPLライセンスです。開発は株式会社カジトリが中心となって行っています。詳細は開発者の方の記事をご覧ください。
GUIのWeb DBというと、なんとなくサイボウズ社のkintoneを連想する方もいるのではないでしょうか。
開発元からはキントーンのキの字も聞こえてきませんが、筆者はひそかにkintoneクローンだと思っていて、かなり可能性を秘めているOSSプロダクトだと考えています。
正直、かなりほれ込んでいるのですが、この記事ではお気に入りポイントは解説しません。また別の機会に。
クラウドでなるべくお安くExmentを運用したい!
ローカルでは、Dockerを使ってExmentを試すことができます。作ってくれた人ありがとう!
ローカルで実際やってみたところ(macOS Mojave、Windows 10 Home WSL2で確認)、あっさり出来ました。すごいですね。
そうしたら、クラウドでホスティングして、外出先などからもアクセスしたくなるというのが人情ですよね。
ホスティング先をいろいろ考えてみました。フロントエンドだけなら、NetlifyやVercelといった無料のサービスもあるのですが、残念ながらこれはバックエンドのシステムです…
先述していますが、Exmentはレンタルサーバーでも運用できます。
Exment公式サイトには、さくらやエックスサーバーといったレンサバでのインストール手順が公開されていますが、残念ながら、さくらやエックスサーバーのアカウントを私は持ち合わせておりません。つまり、筆者はレンサバの契約をしていないのですね。(フロント寄りの作りかけ個人プロダクトがNetlifyやVercelにはわんさかあるんですけど)
Exmentのためだけにレンサバ借りるのもなんだかなあ、だったらVPSのほうが良くない? と色々調べた結果、AmazonのLightsailが私の用途にぴったりだと気付きました。
(なお、筆者はこの時点でVPS、AWS童貞です)
ではさっそくLightsailのアカウントを取得して、始めるぞ!
Lightsailにログインしてからインスタンスの作成あたりまでは、下記記事が詳しいです。
今回は、一番安い$3.5/月の512MBRAMのインスタンスにしました。なるべくお安く、というテーマなので。どうしてもスペック足りなかったら、その時にスケールアップなりなんなり対応を考えようというスタンスです。
Lightsailには、WordPressなどのWebアプリケーションがセットになったインスタンスひな形があるのですが、当然知名度まだまだのExmentひな形というのはありません。
そこで、OSのみのインスタンスを選択します。今回は、CentoOS7を選択しました。
CentOSにフツーにインストールする? それとも…?
Exment公式には、CentOS7にインストールする手順も公開されており、またそれを補強する記事もあります。(下記参照)
が、公式を見ていただければわかる通り、結構な手順があります。で、実際1度やりました。何度か環境を捨てたりやり直したりする過程で「この手順毎回やってられんわ!」となり、他の方法を考えることに至ります。
せや、Dockerそのまま載せたったらええやん?
Lightsail+DockerでExmentを動かす(httpsもあるよ!)
ここからは、ハマりポイントを踏まえた回避策も含めて手順を記します。ここを守れば、最短でExment on Lightsail+Dockerが実現できます。
CentOS7でインスタンス作成後、Docker、Docker-composeとgitをインストールする
では、もろもろインストールしていきます。
毎回、sudo つけるの大変なので、rootになります。
Lightsailでrootになるには、こちらの記事を参考にしました。
$ sudo su -Dockerをインストールします。こちらの記事が詳しいです。
[root@ip-172-xx-xx-x ~]# yum install -y docker # dockerのインストール [root@ip-172-xx-xx-x ~]# service docker start # dockerの起動 [root@ip-172-xx-xx-x ~]# groupadd docker # ユーザー権限で実行できるようにしておく [root@ip-172-xx-xx-x ~]# usermod -g docker centos # 作成したグループにcentosユーザを追加 [root@ip-172-xx-xx-x ~]# sudo /bin/systemctl restart docker.service [root@ip-172-xx-xx-x ~]# docker infoこれでDockerはインストールできました。
続いて、Docker-composeです。[root@ip-172-xx-xx-x ~]# curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose [root@ip-172-xx-xx-x ~]# chmod +x /usr/local/bin/docker-compose [root@ip-172-xx-xx-x ~]# docker-compose --version最後に、Gitをインストールします。CentOS7のyumで入るGitは、1.8.2と古いバージョンのものです。気になる人は、下記記事を参考に新しいのを入れてみてください。今回は、git cloneしたいだけなので、そのままyumでインストールします。
[root@ip-172-xx-xx-x ~]# yum install -y gitこれで、Gitもインストールできました。
スワップ領域を作る
RAM512MBのインスタンスなので、DockerでMySQLまで動かすとメモリ不足になりました。(ハマりポイント1)なので、先んじてスワップ領域を作っておきましょう。
スワップの作り方は下記記事を参考にしました。
[root@ip-172-xx-xx-x ~]# dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progressコマンドの書き方をミスってたため、結構ハマりました(ハマりポイント2)
あれこれ試行錯誤した過程で、/dev/zeroが何のファイルかわかっておらず、rm -rfしちゃったのはいい思い出です。
/dev/zeroを復活させるのは、こちらの記事を参考にしました。
[root@ip-172-xx-xx-x ~]# mknod -m 666 /dev/zero c 1 5 [root@ip-172-xx-xx-x ~]# chown root:mem /dev/zero
status=progressオプションですが、今回はスワップ領域が4Gと大きめなので、しばらくターミナルが沈黙しちゃうと心配です。なので、ddコマンドの進捗をお知らせしてくれるオプションをつけました。下記記事を参考にしています。ddでスワップ領域が作成されたら、粛々と残りの作業を進めます。
[root@ip-172-xx-xx-x ~]# chmod 600 /swapfile #パーミッションの変更 [root@ip-172-xx-xx-x ~]# mkswap /swapfile #スワップの作成 Setting up swapspace version 1, size = 1048572 KiB no label, UUID=d0519bf6-8abf-4c0d-9375-8068c9e5e9a1 [root@ip-172-xx-xx-x ~]# swapon /swapfile #スワップの有効化 [root@ip-172-xx-xx-x ~]# free -m #スワップの確認最後に、スワップの永続化をします。
viで/etc/fstabを開き、/swapfile swap swap defaults 0 0でおしまいです。
git cloneで、docker-compose.ymlとDockerfileを拾ってくる。
先述ご紹介した、ExmentのDockerを作ってくれた方のGithubから拾います。
[root@ip-172-xx-xx-x /home/centos/]# git clone https://github.com/yamada28go/docker-exment.git場所はどこでもいいと思うんですけど、デフォルトユーザーディレクトリ直下にしました。
httpsは?
Dockerでhttpsというと、https-portalが有名なようです。
結論から先にいうと、https-portalを先に設定した状態でExmentをインストールしたら、上手くいきませんでした!!!(ハマりポイント3)
なので、SSLを設定する前に非SSLの状態でExmentのインストールを進めます。
一応、docker-compose.ymlに目を通しておきますか。
docker-compose.ymlversion: '3' services: nginx: image: nginx:latest ports: - 8080:80 volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf - www-data:/var/www depends_on: - php php: build: ./php volumes: - www-data:/var/www depends_on: - db db: image: mysql:5.7 ports: - 13306:3306 volumes: - mysql-data:/var/lib/mysql environment: MYSQL_DATABASE: exment_database MYSQL_ROOT_PASSWORD: secret MYSQL_USER: exment_user MYSQL_PASSWORD: secret phpmyadmin: image: phpmyadmin/phpmyadmin:latest ports: - 8888:80 depends_on: - db # volumes を定義する volumes: # volume の名前を指定 # Exmentのインストールパス www-data: # Compose の外ですでに作成済みの volume を指定する場合は ture を設定する。 # そうすると、 docker-compose up 時に Compose は volume を作成しようとしません。 # かつ、指定した volume が存在しないとエラーを raise します。 #external: true # mysql dbのインストールパス mysql-data:あとでhttps-portalが80番ポートを使うので、nginxが8080になっているのは逆に都合がいいです。特にこのまま何も編集しません。
docker-compose.ymlとDockerfileは何もさわりませんが、php.iniだけは1行だけ追記します。
最後の行に
memory_limit=-1を追記しておきます(ハマりポイント4、詳細は後述)
ではいよいよ…
[root@ip-172-xx-xx-x /home/centos/]# docker-compose up -d初回なので、イメージの取得とビルド、ボリュームの作成をやってくれます。
起動が完了したら、
docker-comopse psで、全コンテナがUpしていることを確認します。(スワップを作っていなかった時は、ここでMySQLがExitしてました)無事起動したら、IPアドレスでアクセスしてみよう
Lightsail側で以下の手順を済ませておきます。
- 静的IPのアタッチ
- ポート8080番の開放
xx.xx.xx.xx:8080にブラウザでアクセスしてみて、Laravelの初期画面が表示されていれば成功です。
xx.xx.xx.xx:8080/adminにアクセスすると、Exmentの初期設定画面になります。
画面は3部構成になっていて、
- 言語とタイムゾーンの指定
- DB設定
- DB設定開始ボタン
の3画面です。何か入力するのは2画面目のDB設定です。
Dockerを使っていますので「ExmentのDocker環境を作ってみた」の記事を参考に、設定を埋めます。
- ホスト名 → db
- データベース名 → exment_database
- ユーザー名 → exment_user
- パスワード → secret
この後、無事インストールが完了すれば、Exmentの初期画面となります。
添付ファイルとかはS3に保存したいじゃんね!
今回のLightsailインスタンスは、保存領域が20GBと、まあ何か動かすのはいいけど、バイナリデータ突っ込んでいったらすぐパンパンになるよね、って容量です。
Exmentには、外部のストレージサービスに各種ファイルを保存するオプションがあります。
せっかくですので、AWSでそろえて、S3に保存させるようにしてみましょう。
S3も童貞でしたので、下記記事を参考にバケットを作成してみました。
Exment側でも設定が必要です。既に
docker-compose exec php bashで立ち上がっているコンテナの中に入ります。[root@ip-172-xx-xx-x /home/centos/]# docker-compose exec php bashこれで、Exmentが動いているphpコンテナの中に入れます。プロンプトの表示がこんな感じに変われば成功です。
root@f54bef27801a:/var/www#つまり、クラウド上にあるLightsailの中にあるDockerコンテナphpの中にいるという二重構造なわけですね。
引き続き、「(上級者向け)ファイルの保存先変更」を読み解きながら、Exment(Laravel)のファイルを修正していきます。
Exmentルートフォルダにある、.envファイルをvimで修正/追記します。
EXMENT_DRIVER_EXMENT=s3 EXMENT_DRIVER_BACKUP=s3 EXMENT_DRIVER_TEMPLATE=s3 EXMENT_DRIVER_PLUGIN=s3 AWS_ACCESS_KEY_ID=(AWS S3のアクセスキー) AWS_SECRET_ACCESS_KEY=(AWS S3のシークレットアクセスキー) AWS_DEFAULT_REGION=(AWS S3のリージョン) AWS_BUCKET_EXMENT=(添付ファイルで使用するAWS S3のバケット) AWS_BUCKET_BACKUP=(バックアップで使用するAWS S3のバケット) AWS_BUCKET_TEMPLATE=(テンプレートで使用するAWS S3のバケット) AWS_BUCKET_PLUGIN=(プラグインで使用するAWS S3のバケット)なお、
EXMENT_DRIVER_xxxはすべて設定する必要はなく、必要があるものだけ設定します。それに紐づくAWS_BUCKET_xxxも必要なものだけでOKです。私は添付ファイルとバックアップデータはS3に保存したかったので、
EXMENT_DRIVER_EXMENT
EXMENT_DRIVER_BACKUP
AWS_BUCKET_EXMENT
AWS_BUCKET_BACKUPの4つのみ設定しました。
最後に、composerでライブラリをインストールします。
先ほど、
docker-compose up -dの前にphp.iniを編集しましたが、Composerはメモリ食いで、すぐPHPのメモリ利用可能上限に達してしまうので、この上限を解除する設定をしたのでした。Composerはインストールに時間がかかるので、時間かかった結果失敗した、って辛いですよね…(筆者はとても悲しかったです。)なので、この設定は
composer requireをする前にもう一度確認しておきましょう。root@f54bef27801a:/var/www# php -i | grep memory_limit memory_limit => -1 => -1-1になっていればOKです。(メモリ上限なし、の意味)
では、いよいよライブラリのインストールです
root@f54bef27801a:/var/www# composer require league/flysystem-aws-s3-v3 ~1.0 -vvv
-vvvオプションは、もっとも粒度細かくログを出す、という意味の指示です。composerはインストールにとても時間がかかるので、長い時間ターミナルが沈黙していると心配になります。なので、逐次ログを出してくれるようにします。このオプションをして長いこと沈黙があれば、それは本当に何かしらの理由で止まっているか、めちゃくちゃ重い処理をしている、ということになります…
S3に添付ファイルをアップするオプションの設定は以上です。適当な画像でもアップして、バケットの中にファイルがあることを確認しましょう。
最後に呪いのhttpsです…
いや、httpsに何の悪いところもないのですが、かなりハマって悩まされたので…
色々やり方が悪かったのかと思い、Docker環境全捨てからの再インストールを何度も行ったので、かなり時間を食ってしまいました。
さっきも言いましたが、docker-composeにhttps-portalも混ぜて書いてしまうと、初回インストールに失敗します。結局はよくわからんエラーに遭遇して詰みました。
インストールは3画面あるといいましたが、最後の3画面目のインストールボタンを押したら、あのLaravelのグレーみの強いエラー画面で
Use of undefined constant STDIN - assumed 'STDIN' (this will throw an Error in a future version of PHP)って出てきて、DBにデータが差し込めないことに。PHPやLaravelに明るくない筆者であるため、ここで断念しました。
httpならちゃんとうまくいったので、結局このエラーをつぶすことはあきらめ、httpでインストール完了させ、その後httpsにするという作戦に切り替えた次第です。
https-portalをdocker-compose.ymlに追記する
https-portalの部分だけ書き出します。
docker-compose.ymlhttps-portal: image: steveltn/https-portal:1 ports: - '80:80' - '443:443' links: - nginx restart: always volumes: - ./certs:/var/lib/https-portal environment: STAGE: 'production' DOMAINS: >- example.com -> http://nginx:8080 depends_on: - php特に難しいことはありません。公式のサンプルとそんなに変わりませんし。ポイントとしては、
enviroment:のSTAGE:が、'production'か'staging'でないと、Let's Encryptの本チャンの証明書はもらえないということです。ここがlocalとか指定なしだと、ローカル開発ってことで、なんちゃって証明書が発行されます。ここも地味にハマりポイントでした(ハマりポイント5)さて、最後に https://example.com/ にアクセスして、Laravelの初期画面が表示されれば晴れて成功です…
と言いたいのですが、まだあります。
https://example.com/admin にアクセスすると、盛大に画面崩れを起こしているじゃないですか!
ブラウザコンソールを見ると、mixed contentでhttpがソースのCSS/JS類が全部ブロッキングされています。
これの対処が最初全然わからなかったのですが、試行錯誤の結果、LaravelおよびLaravel-adminが犯人と断定されました! asset('/css/hoge.css')みたいな記述のところで、http付のパスを出力しちゃってるようです…
以下、この件についての対策です。また
docker-compose exec php bashして中に入ってください。/var/www/exment/.envAPP_ENV=production/var/www/exment/app/Providers/AppProvider.phpclass AppServiceProvider extends ServiceProvider public function boot() { if (config('app.env') === 'production') { \URL::forceScheme('https'); //Schemaじゃなくて、Scheme!!!(ハマりポイント6) } }/var/www/exment/config/admin.php/* |-------------------------------------------------------------------------- | Access via `https` |-------------------------------------------------------------------------- | | If your page is going to be accessed via https, set it to `true`. | */ 'https' => env('ADMIN_HTTPS', true), // ←デフォはfalseなので、trueに!これで、すべてのアセットがhttpsから配信され画面崩れなく表示されるようになりました。
正直、これが本当の意味で正解かどうかわかりません。もしかしたら、AppProvider.phpは不要かもしれません… Laravelのバージョンによってコードの書き方が微妙に違うようでした。これは、本当にたくさんの参考ソースを読みまくって、なんとか動くコードに落ち着いたというのが実情です。
もし、もっと良い方法があるよ、という方はぜひコメント欄で教えてください。
以上、無事動くようになりました!
今のところ、機嫌よく動いてくれています。
セキュリティ等
本記事は検証目的の環境づくりのため、セキュリティ等については触れておりません。詳しい方は補足いただけると助かります。
今後
Exmentの素敵なところをほめまくる記事とか書きたいですね!
- 投稿日:2020-09-08T10:43:51+09:00
Postgresql超初心者が知っておくべきこと
超初心者向けPostgresql入門
IT全般に関する知識が皆無の文系大学生がインターンシップで初めて
Postgresqlを触り、少し苦労したので、知っておくべき基礎中の基礎をご紹介したいと思います。
Postgresqlを初めて触るときに、こういう記事があればよかったなという記事にしたいと思いますので何卒よろしくお願いします。深い理解というよりは、
Postgresqlがざっくりどんな感じのものかということを理解するためにこの記事を読んでいただけるとありがたいです。ちなみに著者のパソコンはMacbookですので、基本的には
MacbookユーザーのPostgresql超初心者向けの記事となっております。Postgresqlとは何ぞや
PostgreSQL(ポストグレスキューエル)はオープンソースのリレーショナルデータベース管理システム(RDBMS)です。
Codezine「Postgresqlとは?」より引用
https://codezine.jp/article/detail/11753簡単に言いますと、
データがたくさん入っているところから欲しいデータがどこにあるのかを調べることができるものです。さらにわかりやすく例を使いますと、
家(データベース)の自室(スキーマ)の中の洋服タンス(テーブル)の中に欲しい服(データ)があるかを調べられるものです。それだけでなく、どこに何が置いてあるかわからないという家を整理整頓してくれるものです。部屋の整理が苦手な方なら、朝起きて急いで家を出たい時に着たい服が見つからないということもよくあるでしょうから、この
Postgresqlが便利であるということはお分かりになるでしょう。Postgresqlを始める前に準備すること
はじめに
HomebrewとDockerをインストールして、ターミナルでPostgresqlを開いてください。
インターン2日目にこの指示を受けた私は脳がパンクしました。順に説明していきます。
ターミナルとは何ぞや
簡単に言いますと、
パソコンに命令する場所です。
ホーム画面でcommand + spaceでSpotlight検索ができますので「ターミナル」と打ってください。
ハッカーみたいなカッコいい画面が出てきます。
これがターミナルです。
Postgresqlを使用する際は基本的にここで作業をすることになります。ちなみに
Postgresqlを開いた状態のコマンドと、ターミナルでのコマンドは違うので要注意!Posgresqlに入れている場合は
データベース名=#
入れていない場合は上画面のように
フォルダ名$
のようになっていますのでわかると思います。Homebrewとは何ぞや
Homebrewとは、Mac OSにおいて、プログラミング上必要となってくる
パッケージをインストールしたりアンインストールしたり出来るシステムです。
このようなものをパッケージ管理システムと呼びます。
つまり、Homebrewを使えば、便利なアイテムのダウンロードが非常に簡単になってきます。プログラミング入門者のための「Homebrew」インストールより引用
https://qiita.com/Naggi-Goishi/items/391b374305bc41b0d9f3わかりやすい説明を引用させていただきました。
今回ではDockerなどのパッケージをインストールするのに便利なものだということです。Homebrewのインストール
Homebrewのホームページを開くと
https://brew.sh/index_jaという風になっており、「Install Homebrew」の下にあるコマンドをターミナルにコピペするとインストールできます。
Dockerとは何ぞや
Docker(ドッカー)は、コンテナ仮想化を用いてアプリケーションを開発・配置・実行するためのオープンソースソフトウェアあるいはオープンプラットフォームである
Wikipedia「Docker」より引用
https://ja.wikipedia.org/wiki/Docker初心者には難しく、私も概念を完全に理解できているわけではありませんが、仮想環境を作ることでPostgresqlなどをサクサク実行できるということです。
Dockerのインストール
Docker公式サイトからDockerのアカウントを作り、Dockerをインストールしてください。
https://hub.docker.com/editions/community/docker-ce-desktop-mac右上のところにクジラのマークが表示されれば成功です。
Postgresqlを開こう
無事
DockerとHomebrewがインストールできた後はいよいよPostgresqlを開きます。
1.まずターミナルを開いて
docker login
と打ち込み、Dockerにログインします。
2.
docker pull postgres
でpostgresqlをインストールします。
3.
docker run --name dev-dash-postgres -e POSTGRES_USER=ユーザー名 -e POSTGRES_PASSWORD=パスワード -p ポート名(初期値だと5432:5432) -d postgres
でDockerを起動します。
4.
psql -h localhost -U ユーザー名
でPostgresqlに接続します。ユーザー名、パスワード、ポート名は自身のものを打ち込んでください。
Dockerがインストールされていなかったりすると実行できないこともあるので注意です。
さあPostgresqlを始めよう
これからより実用的な話に入る前に、Postgresqlの基本原則をお伝えします。
文章を書いたあとには基本的に「;」を絶対につけてください。これなしでは反応しません。
初歩的すぎるからなのかわかりませんが、これを教えてくれる記事が少なかった、、、。気をつけてください。それではこれから
初歩的なコマンド
CREATE TABLE
SELECT
INSERT
を紹介していきます。Postgres覚えておくべき用語
家を例に説明します。
データベース=
家。色んなものが入っている場所。
スキーマ=部屋。自室、倉庫など。データベースよりも小さな括り。
テーブル=タンス。洋服が入っている場所など。スキーマよりも小さな括り。
カラム=タンスの引き出し。下着が入っている引き出しなど。テーブルよりも小さな括り。
データ=洋服。特定の下着、特定のシャツ。CREATE TABLE
用語を理解するのに最適な
「CREATE TABLE」(テーブルを作る)というコマンドを説明いたします。Begginer.sqlCREATE TABLE souko.tansu{スキーマ名.テーブル名} (pants varchar, shirts varchar);{カラム名+データ型}下記のように打ち込みます。
この文頭の
beginner=#のbeginnerがデータベース(家)です。
souko(スキーマ)にtansuというテーブルを作るという形です。
pants,shirts(タンスの引き出し)というカラムをテーブルの中に作ります。この後の
SELECT、INSERTでさらに理解を深めていきましょう。SELECT
Postgresqlで一番使うことになるコマンド「SELECT」をご紹介します。
簡単に言うと「検索」です。
テーブルの中にあるデータを検索したいときに使います。Begginer.sqlSELECT * FROM (スキーマ名.)テーブル名;ここのアスタリスクは
全てを意味します。指定したテーブルの中にあるデータの全てを出したいときには「*」を使用します。全てではなく、特定のものだけを検索したいときには、
カラム名(引き出し)をSELECTの後に入れます。これもわかりやすく、先ほどの家を例に出しますと、
Begginer.sqlSELECT pants FROM souko.tansu;といった形です。
この例えですと、「自分で部屋の中ひっくり返したらすぐ見つかるじゃないか」と思う方がいらっしゃるかもしれませんが、データベースというのは数億件のデータを管理したりもするものです。
数億の服が散らばった部屋の中から欲しい服を取り出すのは、無理です。
INSERT
これもめちゃ使うことになるコマンド「INSERT」。
簡単にいうと「タンスに服入れる(テーブルにデータを入れる)」です。Begginer.sqlINSERT INTO (スキーマ名.)テーブル名(カラム名,カラム名,、、、) values(データ1,データ2,、、、);これを家の例で例えると
Begginer.sqlINSERT INTO souko.tansu(pants, shirts) values('red_pants', 'red_shirts');という風になります。
これはパンツを入れる引き出しに赤のパンツを入れ、シャツを入れる引き出しに赤のシャツを入れるという意味です。同じく
blue_pants,blue_shirtsを入れて、tansu内の全てをSELECTをするとこのようになります。パンツの引き出しだけを見たい時は
Begginer.sqlSELECT pants FROM souko.tansu;と打ち込みます。すると
と出て何のパンツが入っているかを見ることができます。
エラーが出たとき
エラーが出たときはエラーの文言を読んでみて、それでもわからなかった時には文言をコピペしてGoogleで調べましょう。
ただ超初心者だとそれでもよくわからないことの方が多いと思います。そういう時は、どこかしらにエラーがあるのでじっくりと全てを見直していきましょう。
とはいえ、、、。初心者にエラーは地獄
エラーのキツいポイントとして、文言がミスを正しく指摘してくれているわけではないということです。
あくまで例ですが、
Error:そのタンスの中に服無いよ
というエラーが出ているにも関わらず、そのタンス(テーブル)に服(データ)が入っているということがあります。そのような場合は、タンスの場所であったり、タンスを作るときに何かしらのミスが発生しているなどの問題があり、初心者は理解できないことの方が多いです。
私は一つのエラーを調べるのに1日かかったことがあります。(先輩に聞いたら2分で解決してくれました、、、。)
初心者のうちは自分で調べることも大事ですが、本当にわからないときは先輩に聞くというのが、自分にとっても会社にとっても良いと思います。初心者あるあるのミス
セミコロン忘れ
文末に「;」を入れるのを忘れているというのは初心者にはよくあるミスだと思います。
コマンド打ち込んだのに何も実行されない、、、。という場合はとりあえずセミコロンが付いているかどうかを確認してください。パソコン再起動したらPostgres入れないなぜ、、、
パソコンを一度シャットダウンするとDockerから抜けてしまいます。
この場合にはDockerを再起動する必要があります。
Docker start コンテナ名
コンテナ名がわからない場合は
Docker ps -a
で調べられます。まとめ
初心者系の記事でも説明を省いている記事も多いので、超初心者向けとして必要以上にたくさん書きました。
超初心者のほとんどは何となく難しそうだなという印象を抱いていると思いますが、一週間くらいである程度慣れてくると思うので毛嫌いせずに頑張ってください。
- 投稿日:2020-09-08T01:02:48+09:00
Cloud Buildのステップ内でDockerを使うならcloudbuildネットワークを覚えておく
概要
Cloud Buildで
- ステップ内でDockerを使い
- DockerからApplication Default Credentialも使いたい
なら
--network=cloudbuildを渡そうという話です。前提
例にはberglas利用します。
berglasは環境変数に特定フォーマットで秘密情報への参照を入れておくと、その値をとってきてくれます。
例えばFOO=sm://$PROJECT_ID/$SECRET_NAME berglas exec -- barを実行すると、Secret Managerから取ってきた値が環境変数FOOに入ってbarが実行されます。準備
まずSecret Managerで
TESTというシークレットに値を入れておきます。$ echo -n "supersecret" | gcloud beta secrets create TEST --replication-policy automatic --data-file=-またCloud Buildの実行サービスアカウントに、Secret Accesorロールをつけておきます。
$ gcloud projects add-iam-policy-binding $PROJECT_ID \ --member "serviceAccount:$(gcloud projects describe $PROJECT_ID --format 'value(projectNumber)')@cloudbuild.gserviceaccount.com" \ --role roles/secretmanager.secretAccessor実験
実験を単純にする為に
envで環境変数を出力していますが、ログに残るので本当に秘密の情報を扱うならそのまま使わないように気をつけてください。ステップ内部でDockerを使わないのでうまくいく例
まずberglasのイメージを直接使ってみます。
cloudbuild.yamlsteps: - name: 'asia-docker.pkg.dev/berglas/berglas/berglas:latest' args: - 'exec' - '--' - 'env' env: - 'TEST=sm://$PROJECT_ID/TEST'これで実行してみます。
$ gcloud builds submit --config cloudbuild.yaml --no-source ... TEST=supersecret ...復元されたTESTをみることができました。
ダメな例
次にビルドステップ内で
docker run経由でberglasを使ってみます。cloudbuild.yamlsteps: - name: 'gcr.io/cloud-builders/docker' args: - 'run' - '-e' - 'TEST=sm://$PROJECT_ID/TEST' - 'asia-docker.pkg.dev/berglas/berglas/berglas:latest' - 'exec' - '--' - 'env'すると…
$ gcloud builds submit --config cloudbuild.yaml --no-source ... failed to access secret sm://$PROJECT_ID/TEST: failed to access secret: rpc error: code = Unauthenticated desc = transport: Get "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform": dial tcp 169.254.169.254:80: i/o timeout ...エラーが起きてしまいます。DockerコンテナからApplication Default Credential取得リクエストができないようですね。
どんなネットワークがあるのか試しに見てみます。
cloudbuild.yamlsteps: - name: 'gcr.io/cloud-builders/docker' args: - 'network' - 'ls'$ gcloud builds submit --config cloudbuild.yaml --no-source ... NETWORK ID NAME DRIVER SCOPE ed09d11c5bd1 bridge bridge local a01cfc17c577 cloudbuild bridge local f3426b77657b host host local 9b756bf55527 none null local ...Application Default Credentialを使いたい場合には、このうち
cloudbuildネットワークを渡す必要があります。(hostではだめです。)
これはドキュメントにも書いてあります。うまくいく例
cloudbuild.yamlsteps: - name: 'gcr.io/cloud-builders/docker' args: - 'run' - '--network=cloudbuild' # 追加 - '-e' - 'TEST=sm://$PROJECT_ID/TEST' - 'asia-docker.pkg.dev/berglas/berglas/berglas:latest' - 'exec' - '--' - 'env'$ gcloud builds submit --config cloudbuild.yaml --no-source ... TEST=supersecret ...無事見ることができました。
結論
Cloud Buildのステップ内部でDockerコンテナを使い、コンテナからApplication Default Credentialも使いたいなら
--network=cloudbuildを渡しましょう。参考


















