tag:crieit.net,2005:https://crieit.net/tags/uWSGI/feed 「uWSGI」の記事 - Crieit Crieitでタグ「uWSGI」に投稿された最近の記事 2021-01-13T18:21:58+09:00 https://crieit.net/tags/uWSGI/feed tag:crieit.net,2005:PublicArticle/16587 2021-01-13T15:45:49+09:00 2021-01-13T18:21:58+09:00 https://crieit.net/posts/2021-1-13 nginx + uWSGI + Flask で python webアプリを立ち上げる <h1 id="nginx + uWSGI + Flask で python webアプリを立ち上げる"><a href="#nginx+%2B+uWSGI+%2B+Flask+%E3%81%A7+python+web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E7%AB%8B%E3%81%A1%E4%B8%8A%E3%81%92%E3%82%8B">nginx + uWSGI + Flask で python webアプリを立ち上げる</a></h1> <p>開発中は Flask の dev server で良いのだけれど、リリース時にはフロントのHTTPサーバを用意する必要がある。</p> <p>Deployment は選択肢がいくつかあるけれど、今回はUbuntu上で、HTTPサーバに nginx、Flaskで作ったPython Webアプリを動かす WSGIコンテナに uWSGI を使った構成の設定例。</p> <h2 id="インストール"><a href="#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">インストール</a></h2> <p>nginx, uwsgi, Flask をインストールする。uwsgi と Flask は venv 環境で。</p> <pre><code class="shell">$ uname -a Linux hoge-machine 5.4.0-52-generic #57~18.04.1-Ubuntu SMP Thu Oct 15 14:04:49 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux $ sudo apt install nginx $ python3 -V Python 3.6.9 $ mkdir venv; cd venv $ python3 -m venv flaskapp $ source ~/venv/flaskapp/bin/activate (flaskapp) $ pip install -U pip (flaskapp) $ pip install flask uwsgi </code></pre> <h2 id="nginx の設定ファイル"><a href="#nginx+%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB">nginx の設定ファイル</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://flask.palletsprojects.com/en/1.1.x/deploying/uwsgi/#configuring-nginx">https://flask.palletsprojects.com/en/1.1.x/deploying/uwsgi/#configuring-nginx</a></p> <p>flask で uwsgi を使う場合の nginx 設定ファイル例は上に載っているので、それを参考に。<br /> アプリ名を <code>nginx_yourapp</code> とか <code>your_application</code> とかにしているが適当に変える。</p> <p>nginx_yourapp.conf</p> <pre><code class="conf">server { listen 80; listen [::]:80; server_name hoge-machine.com; root /var/www/example.com; index index.html; location = /your_application { rewrite ^ /your_application/; } location /your_application { try_files $uri @your_application; } location @your_application { include uwsgi_params; uwsgi_pass unix:/tmp/your_application.sock; } } </code></pre> <p>nginx の設定ファイルは <code>/etc/nginx/sites-available</code> 下に置いて、<code>/etc/nginx/sites-enabled</code> 下に<br /> シンボリックリンクを張り、サービス再起動する。Permission 関係はよしなに。</p> <pre><code class="shell">$ mkdir -p ~/path/to/nginx_yourapp; cd ~/path/to/nginx_yourapp $ vim nginx_yourapp.conf (上記の設定ファイルを作る) $ cp nginx_yourapp.conf /etc/nginx/sites-available/ $ ln -s /etc/nginx/sites-available/nginx_yourapp.conf /etc/nginx/sites-enabled/nginx_yourapp.conf $ systemctl restart nginx </code></pre> <h2 id="webアプリの準備"><a href="#web%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E6%BA%96%E5%82%99">webアプリの準備</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://flask.palletsprojects.com/en/1.1.x/quickstart/#a-minimal-application">https://flask.palletsprojects.com/en/1.1.x/quickstart/#a-minimal-application</a></p> <p>Flask の HelloWorld。</p> <p>index.py</p> <pre><code class="python">from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "Hello, World!" </code></pre> <h2 id="uwsgi の起動コマンド"><a href="#uwsgi+%E3%81%AE%E8%B5%B7%E5%8B%95%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89">uwsgi の起動コマンド</a></h2> <ul> <li>ソケットファイルは nginx の設定ファイルと合わせること</li> <li><code>--chmod-socket=666</code> はパーミッション関連でこけたら</li> <li><code>--mount</code> はアプリパスと実行するスクリプト名:Flask appオブジェクト名を正しく指定する</li> <li><code>--virtualenv</code> は venv で作ったPython仮想環境を正しく指定する。</li> </ul> <pre><code class="shell">$ uwsgi -s /tmp/nginx_yourapp.sock --chmod-socket=666 --manage-script-name --mount /nginx_yourapp=index:app --virtualenv ~/venv/flaskapp </code></pre> <p>後はブラウザから <code>http://<サーバのIPアドレス>/nginx_yourapp/</code> にアクセスすれば <code>Hello World</code> が表示される。</p> <h2 id="FAQ"><a href="#FAQ">FAQ</a></h2> <h3 id="502 Bad Gateway が出る"><a href="#502+Bad+Gateway+%E3%81%8C%E5%87%BA%E3%82%8B">502 Bad Gateway が出る</a></h3> <p>ソケットファイルの permission 関連がおかしいかも。<br /> <code>/var/log/nginx/error.log</code> あたりを覗くとヒントがあるかも。</p> <h3 id="404 Not Found が出る"><a href="#404+Not+Found+%E3%81%8C%E5%87%BA%E3%82%8B">404 Not Found が出る</a></h3> <p>アプリパス指定が正しくないかも。</p> <h3 id="接続できない"><a href="#%E6%8E%A5%E7%B6%9A%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84">接続できない</a></h3> <p>nginx が正しく動いているなら、 <code>http://<サーバのIPアドレス>/</code> で何かが開けるはず。<br /> ダメならnginxが正しく起動できていないか、そもそもサーバに到達できてないか、<br /> サーバが外からのリクエストを受け付けていないので、そちらの方面でなんとかする。</p> keyangu tag:crieit.net,2005:PublicArticle/15538 2019-11-11T10:57:24+09:00 2019-11-11T10:57:24+09:00 https://crieit.net/posts/Oracle-Django-Nginx-uWSGI Oracle無料ティアでDjango+Nginx+uWSGIでサーバを立ててみる <p>Oracle Cloudで常時無料サービスが開始されたので使ってみた。<br /> 構成は、Django+nginx+uWSGI+Oracle Database+Oracle Linux</p> <p>以下の3つの環境を作ってみたので、その時の備忘録。</p> <ul> <li>ローカルの開発環境</li> <li>ローカルでDockerを使った開発環境</li> <li>コンピュート・インスタンスでの本番環境</li> </ul> <p>とりあえず、Djangoの雛形アプリにアクセスできるまでの簡易なので、<br /> SSL対応などは省いてます。</p> <h3 id="Oracle Cloudの常時無料サービス(無料ティア)について"><a href="#Oracle+Cloud%E3%81%AE%E5%B8%B8%E6%99%82%E7%84%A1%E6%96%99%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%28%E7%84%A1%E6%96%99%E3%83%86%E3%82%A3%E3%82%A2%29%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">Oracle Cloudの常時無料サービス(無料ティア)について</a></h3> <p>新しく常時無料で利用できるようになったサービスたち。<br /> ・<a target="_blank" rel="nofollow noopener" href="https://www.oracle.com/jp/cloud/free/">Oracle Cloud無償ティア | オラクル | Oracle 日本</a></p> <p>利用できるのは、以下のようなもの。</p> <ul> <li>データベース ... 20GBを2つまで</li> <li>コンピュート ... 仮想マシン。1/8 OCPU・1GBを2つまで</li> <li>ストレージ ... 合計100GBの2つのブロック・ボリューム。10GBのオブジェクト・ストレージ</li> </ul> <p>ほかにもロードバランサや監視・通知などある。</p> <p>仮想マシンもデータベースも1アカウントにつき2つまでなので、<br /> 1サービスであれば、ステージング環境と本番環境を用意できそう。</p> <hr /> <h3 id="とりあえずDBを作ってみる"><a href="#%E3%81%A8%E3%82%8A%E3%81%82%E3%81%88%E3%81%9ADB%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">とりあえずDBを作ってみる</a></h3> <p>トップ画面から。</p> <p><img width="1367" alt="oracle_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/dde42040-2f99-5a2a-4824-5894bd4ce59d.png"></p> <p>名前とAdminのパスワードを設定する。<br /> Always FreeもONにしておく。</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/ce050658-f517-7338-ef93-cd0d07893e16.png" alt="oracle_2.png" /></p> <p>「Autonomous Databaseの作成」をクリックすると、プロビジョンがはじまる。<br /> プロビジョンが終わるとこんな感じに。</p> <p><img width="1436" alt="スクリーンショット 2019-11-10 15.59.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/0df9b110-5004-76cd-f942-10780d1c1e39.png"></p> <h5 id="WebブラウザでDBにアクセスしてみる"><a href="#Web%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%A7DB%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">WebブラウザでDBにアクセスしてみる</a></h5> <p>SQL Developer Webからアクセスできる。</p> <p>「DB接続」>「アプリケーション接続」>「SQL Developer Web」にある。<br /> 「アクセスURL」をコピーして、ブラウザに貼り付け。</p> <p><img width="742" alt="oracle_3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/8795616a-9ab4-87a2-cc78-460e9680f30d.png"></p> <p>ログイン画面が表示されるので、DBを作ったときのパスワードを入力。<br /> アカウントは「admin」</p> <p><img width="490" alt="スクリーンショット 2019-11-10 16.00.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/003a489d-23f3-3f50-4cff-a49f674fe002.png"></p> <p>ログインできるとこんな感じ</p> <p><img width="843" alt="スクリーンショット 2019-11-10 16.01.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/485c6462-de41-ad35-6829-33292cce2129.png"></p> <hr /> <h3 id="ローカルの開発環境を作ってみる"><a href="#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AE%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">ローカルの開発環境を作ってみる</a></h3> <p>とりあえず、開発用にローカル環境で<code>python manage.py runserver</code>できるようにする。<br /> ローカルの環境はmacOS Mojave(10.14.6)</p> <h4 id="まずは、Djangoの雛形を作成する"><a href="#%E3%81%BE%E3%81%9A%E3%81%AF%E3%80%81Django%E3%81%AE%E9%9B%9B%E5%BD%A2%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B">まずは、Djangoの雛形を作成する</a></h4> <pre><code class="shell"># pythonのバージョンは3.7.3 $ python3 -V Python 3.7.3 # ディレクトリの作成 $ mkdir sample $ cd sample/ # 仮想環境の作成 $ python3 -m venv venv $ source venv/bin/activate # djangoのインストール $ pip install --upgrade pip $ pip install django # djangoプロジェクトの作成 $ django-admin startproject myproject $ cd myproject $ python manage.py migrate # 起動 $ python manage.py runserver </code></pre> <p>これでとりあえず、デフォルトのデータベース(SQLite)で立ち上がるとこまで完成。</p> <p><img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/e2a487cd-a318-d09c-e9f3-899f598eee09.png" /></p> <h4 id="ローカルでOracleDBを使えるようにする"><a href="#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%A7OracleDB%E3%82%92%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B">ローカルでOracleDBを使えるようにする</a></h4> <h5 id="Oracle Instant Clientのインストール"><a href="#Oracle+Instant+Client%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">Oracle Instant Clientのインストール</a></h5> <p>OracleDBを使うためには、Oracle Instant Clientが必要なので、<br /> 以下からダウンロードしてインストールする。<br /> ・<a target="_blank" rel="nofollow noopener" href="https://www.oracle.com/database/technologies/instant-client/downloads.html">Oracle Instant Client Downloads</a></p> <p>Macだったので、「<a target="_blank" rel="nofollow noopener" href="https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html">Instant Client for macOS (Intel x86)</a>」の「Basic Light Package」を選択</p> <pre><code class="sh">## インストールするディレクトリを作成 $ sudo mkdir -p /opt/oracle ## インストールしたファイルを展開 $ sudo unzip ~/Downloads/instantclient-basiclite-macos.x64-19.3.0.0.0dbru.zip -d /opt/oracle ## ライブラリを参照できるように${HOME}/libにリンクを追加 $ mkdir ~/lib $ ls -s /opt/oracle/instantclient_19_3/libclntsh.dylib ~/lib/ $ cp /opt/oracle/instantclient_19_3/lib* ~/lib/ </code></pre> <h5 id="環境変数にインストールした場所を設定"><a href="#%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%9F%E5%A0%B4%E6%89%80%E3%82%92%E8%A8%AD%E5%AE%9A">環境変数にインストールした場所を設定</a></h5> <pre><code class="shell">echo "export ORACLE_HOME=/opt/oracle/instantclient_19_3" >> ~/.bashrc source ~/.bashrc </code></pre> <h5 id="認証情報の配置"><a href="#%E8%AA%8D%E8%A8%BC%E6%83%85%E5%A0%B1%E3%81%AE%E9%85%8D%E7%BD%AE">認証情報の配置</a></h5> <p>Oracle Cloudの「Autonomous Database」>「Autonomous Databaseの詳細」にある<br /> 「DB接続」からウォレットをダウンロードしてくる。</p> <p><img width="753" alt="oracle_4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/6b23b62d-623d-2fad-ea3b-a95c11d4d605.png"></p> <p>ファイル名は「<code>Wallet_<データベース名>.zip</code>」。<br /> 今回はデータベース名が<code>sample</code>なので、<code>Wallet_sample.zip</code>となる。</p> <pre><code class="shell">## 認証ファイルを配置するディレクトリを作成 $ mkdir -p /opt/oracle/instantclient_19_3/network/admin ## ダウンロードしたウォレットを展開して配置 $ sudo unzip ~/Downloads/Wallet_sample.zip -d ${ORACLE_HOME}/network/admin Archive: ~/Downloads/Wallet_sample.zip inflating: /opt/oracle/instantclient_19_3/network/admin/cwallet.sso inflating: /opt/oracle/instantclient_19_3/network/admin/tnsnames.ora inflating: /opt/oracle/instantclient_19_3/network/admin/truststore.jks inflating: /opt/oracle/instantclient_19_3/network/admin/ojdbc.properties inflating: /opt/oracle/instantclient_19_3/network/admin/sqlnet.ora inflating: /opt/oracle/instantclient_19_3/network/admin/ewallet.p12 inflating: /opt/oracle/instantclient_19_3/network/admin/keystore.jks </code></pre> <h5 id="cx_Oracle(pythonライブラリ)のインストール"><a href="#cx_Oracle%28python%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%29%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">cx_Oracle(pythonライブラリ)のインストール</a></h5> <p>Oracle Databaseのpythonライブラリをインストールする</p> <pre><code>$ pip install cx_Oracle </code></pre> <h5 id="settings.pyの設定"><a href="#settings.py%E3%81%AE%E8%A8%AD%E5%AE%9A">settings.pyの設定</a></h5> <p>settings.pyをOracleように変更。<br /> <code>NAME</code>には、TNS名のどれかを指定する。</p> <p><img width="753" alt="oracle_4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/6b23b62d-623d-2fad-ea3b-a95c11d4d605.png"></p> <p>今回は一番上の<code>sample_HIGH</code>を選択。</p> <pre><code class="python">DATABASES = { 'default': { 'ENGINE': 'django.db.backends.oracle', 'NAME': 'sample_HIGH', 'USER': 'admin', 'PASSWORD': '<DB作成時に入力したパスワード>', } } </code></pre> <p>マイグレーションをもう一度実行してみて、接続できるか確認。</p> <pre><code class="shell">$ python manage.py migrate </code></pre> <p>マイグレーションが成功すると、Webブラウザ上のSQL Developerでも確認できる。</p> <p><img width="926" alt="スクリーンショット 2019-11-10 16.35.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/53393a83-0772-2f8e-9814-6d2ddbe203bd.png"></p> <p>これで、とりあえず、開発できるようになった(<em>´ω`</em>)</p> <hr /> <h3 id="ローカルでDockerを使った開発環境を作ってみる"><a href="#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%A7Docker%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">ローカルでDockerを使った開発環境を作ってみる</a></h3> <p>実際にデプロイする際は、NginxとuWSGIを利用するので、<br /> それを試せる環境をDockerで構築する。</p> <h4 id="Django側の変更"><a href="#Django%E5%81%B4%E3%81%AE%E5%A4%89%E6%9B%B4">Django側の変更</a></h4> <p>nginx+uWSGIで動かすために、いくつか変更。</p> <h5 id="1. STATIC_ROOTとALLOWED_HOSTS設定"><a href="#1.+STATIC_ROOT%E3%81%A8ALLOWED_HOSTS%E8%A8%AD%E5%AE%9A">1. STATIC_ROOTとALLOWED_HOSTS設定</a></h5> <p>settings.pyを以下の感じに変更。<br /> ログファイルも出るように変更。</p> <pre><code class="diff">-ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ["127.0.0.1"] ... STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, "static/") +# for logging +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + + 'formatters': { + 'standard': { + 'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s", + 'datefmt': "%d/%b/%Y %H:%M:%S" + }, + }, + 'handlers': { + 'file': { + 'level': 'INFO', + 'class': 'logging.handlers.RotatingFileHandler', + 'filename': 'django.log', + 'maxBytes': 50000, + 'backupCount': 2, + 'formatter': 'standard', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} </code></pre> <h5 id="2. staticディレクトリを作成&amp;配置"><a href="#2.+static%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%82%92%E4%BD%9C%E6%88%90%26amp%3B%E9%85%8D%E7%BD%AE">2. staticディレクトリを作成&配置</a></h5> <p>manage.pyと同じ場所に作成し、<br /> django-adminのcssとかを配置</p> <pre><code class="shell">$ mkdir static $ python manage.py collectstatic </code></pre> <h4 id="Docker用の資材を配置"><a href="#Docker%E7%94%A8%E3%81%AE%E8%B3%87%E6%9D%90%E3%82%92%E9%85%8D%E7%BD%AE">Docker用の資材を配置</a></h4> <pre><code class="shell"># Docker用の資材の配置場所を作成 $ mkdir docker # 資格情報の配置 $ mkdir docker/wallet $ unzip ~/Downloads/Wallet_sample.zip -d docker/wallet/ Archive: ~/Downloads/Wallet_sample.zip inflating: wallet/cwallet.sso inflating: wallet/tnsnames.ora inflating: wallet/truststore.jks inflating: wallet/ojdbc.properties inflating: wallet/sqlnet.ora inflating: wallet/ewallet.p12 inflating: wallet/keystore.jks # NginxやuWSGIの設定ファイルは以下に配置 $ mkdir docker/conf $ touch docker/conf/requirements.txt $ touch docker/conf/myproject_nginx.conf $ touch docker/conf/myproject_uwsgi.ini $ touch docker/conf/uwsgi.service # Dockerfireとdocker-compose.ymlを配置 $ touch docker/Dockerfile $ touch docker-compose.yml </code></pre> <p>ディレクトリ的にはこんな感じ。</p> <pre><code>. ├── docker/ │   ├── conf/ │   │   ├── myproject_nginx.conf │   │   ├── myproject_uwsgi.ini │   │   └── uwsgi.service │   ├── wallet │   │   ├── ... │   │   └── tnsnames.ora │   ├── Dockerfile │   └── requirements.txt ├── myproject/ │   ├── myproject/ │   │   ├── settings.py │   │   └── wsgi.py │   ├── static/ │   └── manage.py ├── venv/ └── docker-compose.yml </code></pre> <p>各ファイルの中身は以下の感じ。</p> <h5 id="docker-compose.yml"><a href="#docker-compose.yml">docker-compose.yml</a></h5> <pre><code class="yml">version: '2' services: web: build: "./docker" volumes: # djangoアプリを/var/www配下にマウント - ./myproject:/var/www/myproject ports: # 80および8000ポートを開けておく - "80:80" - "8000:8000" # systemctlを使うので特権を有効にしておく privileged: true command: /sbin/init </code></pre> <h5 id="docker/Dockerfile"><a href="#docker%2FDockerfile">docker/Dockerfile</a></h5> <pre><code class="dockerfile"># Oracle Cloud Infrastructureでも # OracleLinuxを使うのでoraclelinuxのイメージを使う FROM oraclelinux:7 ### ENV ENV ORACLE_HOME "/usr/lib/oracle/18.3" ### INSTALL ORACLE DATABASE # oracle-instantclientを利用するために、2つリポジトリを有効化 RUN yum install -y oracle-release-el7 oracle-softwarecollection-release-el7 RUN yum install -y oracle-instantclient18.3-basiclite RUN echo /usr/lib/oracle/18.3/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf RUN mkdir -p ${ORACLE_HOME}/network/admin COPY wallet/* ${ORACLE_HOME}/network/admin/ ### INSTALL PYTHON # python3-develを利用するために、ol7_optional_latestを有効化 RUN yum-config-manager --enable ol7_optional_latest RUN yum install -y python3 python3-devel gcc ### CREATE VIRTUAL ENV RUN mkdir /var/www/ RUN mkdir /var/www/myproject WORKDIR /var/www/ RUN python3 -m venv venv # 作成した仮想環境(venv)にactivateする ENV PATH="/var/www/venv/bin:$PATH" COPY requirements.txt /var/www/ RUN pip install -r requirements.txt #### INSTALL NGINX RUN yum install -y nginx COPY conf/myproject_nginx.conf /etc/nginx/conf.d/ RUN systemctl enable nginx RUN chown -R nginx.nginx /var/www RUN chmod 755 /var/www ### SETUP uWSGI Emperor mode RUN mkdir /etc/uwsgi RUN mkdir /etc/uwsgi/vassals COPY conf/myproject_uwsgi.ini /etc/uwsgi/vassals # uWSGIのログディレクトリを作成 RUN mkdir /var/log/uwsgi RUN chown -R nginx:nginx /var/log/uwsgi # uWSGIをサービスに登録 COPY conf/uwsgi.service /etc/systemd/system/ RUN systemctl enable uwsgi </code></pre> <h5 id="docker/conf/requirements.txt"><a href="#docker%2Fconf%2Frequirements.txt">docker/conf/requirements.txt</a></h5> <pre><code class="txt">Django==2.2.7 cx-Oracle==7.2.3 uWSGI==2.0.18 </code></pre> <h5 id="docker/conf/myproject_nginx.conf"><a href="#docker%2Fconf%2Fmyproject_nginx.conf">docker/conf/myproject_nginx.conf</a></h5> <pre><code class="nginx"># the upstream component nginx needs to connect to upstream django { # myproject_uwsgi.iniで設定したsocketファイルを指定 # unix://<socketファイルのパス> server unix:///var/www/myproject.sock; } # configuration of the server server { listen 80; # IPアドレスを指定。ローカルなので、127.0.0.1を設定 server_name 127.0.0.1; charset utf-8; # Django static location /static { alias /var/www/myproject/static; } # Finally, send all non-media requests to the Django server. location / { include uwsgi_params; uwsgi_pass django; } } </code></pre> <h5 id="docker/conf/myproject_uwsgi.ini"><a href="#docker%2Fconf%2Fmyproject_uwsgi.ini">docker/conf/myproject_uwsgi.ini</a></h5> <pre><code class="ini">[uwsgi] # Djangoプロジェクトのパスを指定 chdir = /var/www/myproject # Djangoプロジェクトのwsgi.pyを指定 module = myproject.wsgi # venvのパスを指定 home = /var/www/venv # process-related settings: master master = true # maximum number of worker processes processes = 10 # socketファイルののパス socket = /var/www/myproject.sock # socketファイルのユーザと権限を設定 chown-socket = nginx:nginx chmod-socket = 666 # clear environment on exit vacuum = true # logfile logto = /var/log/uwsgi/%n.log </code></pre> <h5 id="docker/conf/uwsgi.service"><a href="#docker%2Fconf%2Fuwsgi.service">docker/conf/uwsgi.service</a></h5> <pre><code>[Unit] Description=uWSGI Emperor After=syslog.target [Service] User=nginx Group=nginx # 環境変数の設定 Environment="ORACLE_HOME=/usr/lib/oracle/18.3" Environment="LD_LIBRARY_PAT=${ORACLE_HOME}/client64/lib:$LD_LIBRARY_PATH" Environment="PATH=$PATH:${ORACLE_HOME}/client64/lib" # EmperorモードでuWSGIを実行。venvにあるuwsgiを使う ExecStart=/var/www/venv/bin/uwsgi --master --emperor /etc/uwsgi/vassals --die-on-term --uid nginx --gid nginx --logto /var/log/uwsgi/emperor.log Restart=always KillSignal=SIGQUIT Type=notify StandardError=syslog NotifyAccess=all [Install] WantedBy=multi-user.target </code></pre> <h4 id="Dockerを起動"><a href="#Docker%E3%82%92%E8%B5%B7%E5%8B%95">Dockerを起動</a></h4> <pre><code class="shell"># dockerを立ち上げ $ docker-compose up -d </code></pre> <p>これでうまくビルドされて立ち上がれば、<br /> <code>http://127.0.0.1</code>にアクセスできる。</p> <p><code>myproject_nginx.conf</code>の<code>server_name</code>で、<code>127.0.0.1</code>を指定しているので、<br /> <code>http://127.0.0.1</code>じゃないとDjangoアプリにアクセスできないので注意。</p> <p><code>http://localhost</code>だと、<code>myproject_nginx.conf</code>の設定が適用されず、<br /> nginxのデフォルトページが表示される。</p> <h5 id="よく使うログインとか停止とかはこんな感じ。"><a href="#%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%A8%E3%81%8B%E5%81%9C%E6%AD%A2%E3%81%A8%E3%81%8B%E3%81%AF%E3%81%93%E3%82%93%E3%81%AA%E6%84%9F%E3%81%98%E3%80%82">よく使うログインとか停止とかはこんな感じ。</a></h5> <pre><code class="shell"># コンテナにログイン $ docker-compose exec web /bin/bash # 停止 $ docker-compose stop # 削除 $ docker-compose rm # Dockerfile ビルド $ docker-compose build # Dockerfile ビルド(キャッシュなし) $ docker-compose build --no-cache # コンテナをせんぶ削除 $ docker rm `docker ps -a -q` </code></pre> <h5 id="うまくいかないときにみるところ"><a href="#%E3%81%86%E3%81%BE%E3%81%8F%E3%81%84%E3%81%8B%E3%81%AA%E3%81%84%E3%81%A8%E3%81%8D%E3%81%AB%E3%81%BF%E3%82%8B%E3%81%A8%E3%81%93%E3%82%8D">うまくいかないときにみるところ</a></h5> <p>以下の場所にログファイルが出力されるので見てみる。</p> <ul> <li><code>/var/log/messages</code> ... systemdのログ</li> <li><code>/var/log/nginx/error.log</code> ... nginxのエラーログ</li> <li><code>/var/log/uwsgi/emperor.log</code> ... uWSGI Emperorのログ</li> <li><code>/var/log/uwsgi/myproject_uwsgi.log</code> ... myproject_uwsgi.iniのログ</li> <li><code>/var/www/myproject/django.log</code> ... Djangoプロジェクトのログ</li> </ul> <p>あとは、「パスが正しいか」「権限、オーナーが正しいか」などを見てみるといいかも。</p> <hr /> <h3 id="コンピュート・インスタンスで公開してみる"><a href="#%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%83%88%E3%83%BB%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%A7%E5%85%AC%E9%96%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B">コンピュート・インスタンスで公開してみる</a></h3> <h4 id="仮想インスタンスの作成"><a href="#%E4%BB%AE%E6%83%B3%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%AE%E4%BD%9C%E6%88%90">仮想インスタンスの作成</a></h4> <p>ここから選択。</p> <p><img width="1367" alt="oracle_5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/58f5c6f6-a84b-435e-eadf-96a795fe8ba8.png"></p> <p>こんな感じで入力。<br /> 「<strong>パブリックIPアドレスの割当</strong>」を選択しておく。</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/71e54b71-dad2-9b33-3120-73ef26aae734.png" alt="oracle_6.png" /></p> <p>ちゃんと「パブリックIPアドレスの割当」を選択していると、<br /> ここにIPアドレスが表示される</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/2a714a85-2389-506d-4a8c-9197fb9ca208.png" alt="oracle_7.png" /></p> <p>デフォルトのユーザは<code>opc</code>なので、<br /> こんな感じで、sshでログインできる。</p> <pre><code class="shell">$ ssh opc@<IPアドレス> </code></pre> <h4 id="セキュリティルールを設定"><a href="#%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%83%AB%E3%83%BC%E3%83%AB%E3%82%92%E8%A8%AD%E5%AE%9A">セキュリティルールを設定</a></h4> <p>HTTP(ポート80)でアクセスできるようにセキュリティルールを設定する<br /> ただ、セキュリティルールを設定する場所は少しわかりにくい。。</p> <p>仮想インスタンスの詳細にアクセスして、<br /> 「仮想クラウド・ネットワーク」を選択</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/8c83e806-cb22-481f-a7c4-1903c7766685.png" alt="oracle_8.png" /></p> <p>左下に「ネットワーク・セキュリティ・グループ」を選択。<br /> 「ネットワーク・セキュリティ・グループの作成」を選択すると、追加できるようになる。</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/107254d4-5c9f-155d-5fb2-f9ba13c9d621.png" alt="oracle_9.png" /></p> <p>「名前」と「コンパートメント」に作成を設定</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/4464efc9-a245-3858-707c-811f12a166d9.png" alt="oracle_10.png" /></p> <p>ルールの追加を以下のように設定して、「作成」をクリック</p> <p><img width="1404" alt="oracle_11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/f604553d-7ea4-925d-944b-2410bd920e91.png"></p> <p>これで作成できたので、仮想インスタンスの詳細にもどって、<br /> 「ネットワーク・セキュリティ・グループ」の「編集」を選択</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/8c96405c-539f-9197-40b0-782c30b85079.png" alt="oracle_12.png" /></p> <p>さっき作ったセキュリティグループを設定</p> <p><img width="783" alt="スクリーンショット 2019-11-11 0.19.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/12823048-83d2-1278-68a6-dcd45dace136.png"></p> <h4 id="環境構築"><a href="#%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89">環境構築</a></h4> <p>Dockerfileでやったような感じで、<br /> Django+nginx+uWSGIな環境を構築してく。</p> <p>DockerイメージのOracleLinuxとは違い、</p> <ol> <li>リポジトリが最初から有効化されている</li> <li>SELinuxが有効化されている</li> </ol> <p>という感じなので、ちょっと変更が必要。</p> <h5 id="資材を仮想インスタンスに送る"><a href="#%E8%B3%87%E6%9D%90%E3%82%92%E4%BB%AE%E6%83%B3%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%AB%E9%80%81%E3%82%8B">資材を仮想インスタンスに送る</a></h5> <p>Dockerのときに使った資材を仮想インスタンスに送る。</p> <pre><code class="shell">$ scp -r docker opc@<IPアドレス>:~/ $ scp -r myproject/ opc@<IPアドレス>:~/ </code></pre> <p>送信したら、ログインして確認。</p> <pre><code class="shell">$ ssh opc@<IPアドレス> $ pwd /home/opc $ ls docker myproject </code></pre> <p>ログイン後のディレクトリ構成はこんな感じ</p> <pre><code>/home/opc ├── docker/ │   ├── conf/ │   │   ├── myproject_nginx.conf │   │   ├── myproject_uwsgi.ini │   │   └── uwsgi.service │   ├── wallet │   │   ├── ... │   │   └── tnsnames.ora │   ├── Dockerfile │   └── requirements.txt ├── myproject/ │   ├── myproject/ │   │   ├── settings.py │   │   └── wsgi.py │   ├── static/ │   └── manage.py ├── venv/ └── docker-compose.yml </code></pre> <h5 id="設定ファイルの変更"><a href="#%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%A4%89%E6%9B%B4">設定ファイルの変更</a></h5> <p>IPアドレスと<code>127.0.0.1</code>にしていたので変更する。</p> <h6 id="~/docker/conf/myproject_nginx.conf"><a href="#%7E%2Fdocker%2Fconf%2Fmyproject_nginx.conf">~/docker/conf/myproject_nginx.conf</a></h6> <pre><code class="diff"> server { - server_name 127.0.0.1; + server_name <IPアドレス>; } </code></pre> <h6 id="~/myproject/myproject/settings.py"><a href="#%7E%2Fmyproject%2Fmyproject%2Fsettings.py">~/myproject/myproject/settings.py</a></h6> <pre><code class="diff">-ALLOWED_HOSTS = ["127.0.0.1"] +ALLOWED_HOSTS = ["<IPアドレス>"] </code></pre> <h5 id="環境構築の実施"><a href="#%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E3%81%AE%E5%AE%9F%E6%96%BD">環境構築の実施</a></h5> <pre><code class="shell">$ sudo -s ### INSTALL ORACLE DATABASE $ yum install -y oracle-instantclient18.3-basiclite $ echo /usr/lib/oracle/18.3/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf $ mkdir -p /usr/lib/oracle/18.3/network/admin $ /home/opc/docker/wallet/* /usr/lib/oracle/18.3/network/admin/ ### INSTALL PYTHON $ yum install -y python3 python3-devel gcc ### CREATE VIRTUAL ENV $ mkdir /var/www/ $ cp -r /home/opc/myproject /var/www $ cd /var/www/ $ python3 -m venv venv # 作成した仮想環境(venv)にactivateする $ source venv/bin/activate $ pip install -r /home/opc/docker/requirements.txt #### INSTALL NGINX $ yum install -y nginx $ cp /home/opc/docker/conf/myproject_nginx.conf /etc/nginx/conf.d/ $ systemctl enable nginx $ chown -R nginx.nginx /var/www # $ chmod 755 /var/www ### SETUP uWSGI Emperor mode $ mkdir -p /etc/uwsgi/vassals $ cp /home/opc/docker/conf/myproject_uwsgi.ini /etc/uwsgi/vassals # uWSGIのログディレクトリを作成 $ mkdir /var/log/uwsgi $ chown -R nginx:nginx /var/log/uwsgi # uWSGIをサービスに登録 $ cp /home/opc/docker/conf/uwsgi.service /etc/systemd/system/ $ systemctl enable uwsgi ##### ここから仮想インスタンス独自の設定 ### Firewallの設定 # httpを追加する $ firewall-cmd --permanent --add-service=http # firewallを再起動して変更を反映 $ systemctl restart firewalld.service ### SELinuxの設定 $ restorecon -RF /var/www ### サービスの起動 $ systemctl restart nginx $ systemctl restart uwsgi </code></pre> <p>一度、<code>http://<IPアドレス></code>にアクセスして確認してみる。<br /> エラーページが出ていたら、以下を実行</p> <pre><code class="shell"># 監査ログを確認 $ cat /var/log/audit/audit.log | grep nginx | audit2allow -m nginx # ポリシーファイルを作成 $ cat /var/log/audit/audit.log | audit2allow -M nginx # ポリシーファイルを適用 $ semodule -i nginx.pp </code></pre> <p>これで、<code>http://<IPアドレス></code>にアクセスして、<br /> Djangoの画面が表示されて、django-adminの画面が操作できればOK</p> <h1 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h1> <p>とりあえず、ローカルとインスタンス上の環境が作れたので、<br /> 色々することはできそう(<em>´ω`</em>)</p> <p>SSL対応、権限周りなど、本番としては足りないところがあるので、<br /> そのあたりは他の記事を参照ください〜ヽ(=´▽`=)ノ</p> <h2 id="こんなのつくってます!!"><a href="#%E3%81%93%E3%82%93%E3%81%AA%E3%81%AE%E3%81%A4%E3%81%8F%E3%81%A3%E3%81%A6%E3%81%BE%E3%81%99%21%21">こんなのつくってます!!</a></h2> <p>積読用の読書管理アプリ 『積読ハウマッチ』をリリースしました!<br /> <a target="_blank" rel="nofollow noopener" href="https://tsundoku.site">積読ハウマッチ</a>は、Nuxt.js+Firebaseで開発してます!</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/572d4947-f40b-e4dc-1c9c-bc584cd2a66c.png" width="200"/></p> <p>もしよかったら、遊んでみてくださいヽ(=´▽`=)ノ</p> <p>要望・感想・アドバイスなどあれば、<br /> 公式アカウント(<a target="_blank" rel="nofollow noopener" href="https://twitter.com/MemoryLoverz">@MemoryLoverz</a>)や開発者(<a target="_blank" rel="nofollow noopener" href="https://twitter.com/kira_puka">@kira_puka</a>)まで♪</p> <h1 id="参考にしたサイトさま"><a href="#%E5%8F%82%E8%80%83%E3%81%AB%E3%81%97%E3%81%9F%E3%82%B5%E3%82%A4%E3%83%88%E3%81%95%E3%81%BE">参考にしたサイトさま</a></h1> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://docs.djangoproject.com/ja/2.2/ref/databases/#oracle-notes">データベース | Django ドキュメント | Django</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://oracle.github.io/python-cx_Oracle/">cx_Oracle - Python Interface for Oracle Database</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html">cx_Oracle 7 Installation — cx_Oracle 7.3.0-dev documentation</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html#ic_osx_inst">Instant Client for macOS (Intel x86)</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://oracle.github.io/odpi/doc/installation.html#macos">ODPI-C Installation — ODPI-C v3.2.2</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://shase428.hatenablog.jp/entry/2018/01/31/201543">Macでsqlplus使えるようにするメモ - ビットの海</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/oracle/python-cx_Oracle/issues/56">trouble running Oracle_cx on macOS · Issue #56 · oracle/python-cx_Oracle</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.oracle.com/cd/E83857_01/iaas/compute-iaas-cloud/stcsg/accessing-oracle-linux-instance-using-ssh.html#GUID-D313B1A1-FB67-42C7-A7CC-958656A5207F">SSHを使用したOracle Linuxインスタンスへのアクセス</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://cloudii.atomitech.jp/entry/20190417/1555464532">コンピュート・インスタンスに予約済パブリックIPを付与する - Cloudii blog</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/chi9rin/items/af532d0dd9237cc65741#selinux-%E3%81%AE%E5%8B%95%E4%BD%9C%E3%83%A2%E3%83%BC%E3%83%89">SELinux を使おう.使ってくれ. - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://serverfault.com/questions/413397/how-to-set-environment-variable-in-systemd-service">arch linux - How to set environment variable in systemd service? - Server Fault</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/cof123/items/6c9d4b01f0057a9a8de0">EC2にnginx+uwsgi+python でHello World - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/takahirono7/items/fd6f9239f0f88eb65a7c">uwsgiのsystemd化(pyenv環境) - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yasunori/items/64606e63b36b396cf695#%E3%83%AD%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%86%E3%83%BC%E3%83%88%E3%81%A7%E3%83%AD%E3%82%B0%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E8%A6%8B%E5%A4%B1%E3%82%8F%E3%81%AA%E3%81%84">ちゃんと運用するときのuWSGI設定メモ - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.saintsouth.net/blog/setup-django-app-with-uwsgi-and-nginx/#toc-9">Nginx に uWSGI + Django アプリ を組み込む | SaintSouth.NET</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/5t111111/items/e170fead91261621b054#uwsgi-emperor">Ubuntu 12.04でpyenvを利用して速攻でPython3.4 + Nginx + uWSGI + FlaskなWebアプリケーション実行環境を作る - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.mathpython.com/ja/django-nginx-conf/">nginxでDjangoを使うときの設定ファイル:クライアント、nginx、uwsgiの流れを整理しよう - MathPython</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html">Setting up Django and your web server with uWSGI and nginx — uWSGI 2.0 documentation</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://pythonspeed.com/articles/activate-virtualenv-dockerfile/">Elegantly activating a virtualenv in a Dockerfile</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/hana_shin/items/bd9ba363ba06882e1fab">firewall-cmdコマンドの使い方 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/yakumo/items/8ac195337414aabd39c0">Oracle Cloud で Compute にWebサーバーを立てたメモ - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e">venv: Python 仮想環境管理 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="http://blog.higty.xyz/archives/242/">SELinux + Nginx ポリシー設定 - URAGAMI</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.blog.umentu.work/centos7nginx-selinux%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%83%9B%E3%83%BC%E3%83%A0%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E9%85%8D%E4%B8%8B%E3%81%AEweb%E3%82%B3%E3%83%B3%E3%83%86/">[CentOS7][Nginx] SELinuxを設定しホームディレクトリ配下のWebコンテンツを公開を許可 | from umentu import stupid</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/tifa2chan/items/e9aa408244687a63a0ae#%E5%81%9C%E6%AD%A2%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E7%A2%BA%E8%AA%8D">Dockerイメージとコンテナの削除方法 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/gold-kou/items/44860fbda1a34a001fc1#rm">いまさらDockerに入門したので分かりやすくまとめます - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/okhrn/items/d8580e66546d166f489a">Dockerネットワーク設定 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa">Docker Compose - docker-compose.yml リファレンス - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/tifa2chan/items/e9aa408244687a63a0ae">Dockerイメージとコンテナの削除方法 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/prgseek/items/e557a371d7bd1f57b9b1#-docker-composeyml">Docker Compose で複数コンテナ構築&管理 - Qiita</a></li> </ul> きらぷか@積読ハウマッチ/SSSAPIなど