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ディレクトリを作成&配置"><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など