LightsailでCentOS&Docker&Djangoのサイトを構築する
以下、完全に自分流のやり方ですが、動作はします。
この記事の前提条件
・linuxにssh接続できること
・linux操作の基本を知っていること
・bashのシェルスクリプトでhello worldくらいは理解していること
・vimの操作ができること
・Docker操作とDocker-composeを理解していること
環境変数を使うために.bash_profileを編集する
以下、Lightsailにssh接続してから、実行して下さい。
// 環境変数を設定する (export する変数)は、.bash_profileに書くと捗りそう。
$ echo export work_id="10" >> ~/.bash_profile
$ echo export workDirPath="/srv/10" >> ~/.bash_profile
又は
$ vim ~/.bash_profile
(iで編集を開始する)
(次の行を追加する)
export work_id=10
export workDirPath=/srv/${work_id}
(escを押して、:wqを押して保存して閉じる)
$ cat ~/.bash_profile
// 再起動せずに、反映させる
$ source ~/.bash_profile
// 確認
$ echo ${work_id} && echo ${workDirPath}
10
/srv/10
以上の環境変数の設定でわかるように、この記事ではlinuxのディレクトリの中の/srvという場所にファイルを展開していきます。
docker-compose.ymlでdjangoコンテナ、nginxコンテナ、mysqlコンテナを作成
/srvを利用したいので、srvディレクトリの所有者を変更します。
// 事前確認
$ ls -al /
drwxr-xr-x. 2 root root 6 4月 11 2018 srv
// /srvをmkdirするために、chownで所有者をrootからcentosにする
$ sudo chown -R centos:centos /srv
// 事後確認
$ ls -al /
drwxr-xr-x. 2 centos centos 6 4月 11 2018 srv
vimでシェルスクリプトを作成します。以下のオレンジの文字からオレンジの文字までコピーして、vimで開いたファイルにペーストして下さい。
bash -c ・・・コピペのため、ワンライナーで書きたいのでcオプションを利用してます。
// (環境変数の設定&ディレクトリ作成&ファイル作成)
$ bash -c "mkdir ${workDirPath} && vim ${workDirPath}/make1.sh"
(iで編集を開始する)
#!bin/bash
# まずは環境変数が設定されているかの確認。
if [ -z "${work_id}" ]; then
echo "\$work_idが空です。"
exit 0
fi
if [ -z "$workDirPath" ]; then
echo "\$workDirPathが空です。"
exit 0
fi
mkdir -p ${workDirPath}/django
# DjangoコンテナのDockerfileの作成
cat <<EOS > ${workDirPath}/django/Dockerfile
FROM python
RUN pip install -U pip && \
mkdir /DjangoContainer
WORKDIR /DjangoContainer
COPY requirements.txt /DjangoContainer/requirements.txt
RUN pip install -r requirements.txt
EOS
# requirements.txt(pipでインストールするライブラリを記録するファイル)を作成
cat <<EOS > ${workDirPath}/django/requirements.txt
Django==2.0.4
uwsgi==2.0.17
PyMySQL==0.8.0
pytest
EOS
# Dockerfileの作成より上で実行する
mkdir -p ${workDirPath}/mysql/conf.d
# mySQLコンテナのDockerfileの作成
cat <<EOS > ${workDirPath}/mysql/Dockerfile
FROM mysql:5.6
RUN apt-get update && \
apt-get install -y locales && \
rm -rf /var/lib/apt/lists/* && \
echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
EOS
# my.cnfの作成
# 文字化けさせないためだったり、全角文字を入力できるようにするためだったりの設定
cat <<EOS > ${workDirPath}/mysql/conf.d/my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
[client]
default-character-set=utf8mb4
EOS
mkdir -p ${workDirPath}/mysql/init
# mySQLの起動時のテーブルの作成
cat <<EOS > ${workDirPath}/mysql/init/1_comment.sql
create database if not exists web_db;
use web_db;
create table t_Comment (
ID int,
Text varchar(255),
Name varchar(255),
VoteDate Date
);
INSERT INTO t_Comment (ID, Text, Name) VALUES (1, 'はじめまして','森蘭丸');
INSERT INTO t_Comment (ID, Text, Name) VALUES (2, 'ういヤツよ','織田信長');
EOS
# docker-compose.ymlの作成
cat <<EOS > ${workDirPath}/docker-compose.yml
version: '3'
services:
mysql_i${work_id}:
build: ${workDirPath}/mysql
container_name: ${work_id}_mysql
restart: always
#↓MySQLの文字コードの設定。日本語入力。
#command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
ports:
- "33${work_id}:3306"
# - "3306:3306"
environment:
MYSQL_DATABASE: web_db
MYSQL_USER: username
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: root
TZ: "Asia/Tokyo"
volumes:
# 永続化のディレクトリ
- ${workDirPath}/mysql/data:/var/lib/mysql
# 公式のmysqlイメージの場合、docker-entrypoint-initdb.dに置かれているファイルは
# docker起動時に自動で実行される。つまり、初期化のディレクトリ。
- ${workDirPath}/mysql/init:/docker-entrypoint-initdb.d
# 設定
- ${workDirPath}/mysql/conf.d:/etc/mysql/conf.d
django_i${work_id}:
build: ${workDirPath}/django
tty: true
container_name: ${work_id}_django
restart: always
command: >
/bin/bash -c "chmod 755 /DjangoContainer/start.sh &&
bash /DjangoContainer/start.sh"
volumes:
- ${workDirPath}/django:/DjangoContainer
#ports:
#- "81${work_id}:81${work_id}"
expose:
- "81${work_id}"
depends_on:
- mysql_i${work_id}
nginx_i${work_id}:
image: nginx:1.17.2
container_name: ${work_id}-nginx
restart: always
ports:
- "80:80"
#- "81${work_id}:8010"
depends_on:
- django_i${work_id}
volumes:
- ${workDirPath}/nginx/conf.d:/etc/nginx/conf.d
- ${workDirPath}/nginx/uwsgi_params:/etc/nginx/uwsgi_params
#- ${workDirPath}/nginx/public:/usr/share/nginx/html
networks:
default:
external:
name: shared
EOS
mkdir -p ${workDirPath}/nginx/conf.d
#=====================
# my_nginx.confの作成
#=====================
cat <<EOS > ${workDirPath}/nginx/conf.d/my_nginx.conf
upstream djangoo {
ip_hash;
server ${work_id}_django:81${work_id};
}
server {
listen 80;
#server_name localhost;
location / {
uwsgi_pass djangoo;
include /etc/nginx/uwsgi_params;
root /usr/share/nginx/html;
index index.html index.htm;
}
}
#versionを隠す
server_tokens off;
#ログの保存ファイルの指定
#access_log /var/log/nginx/access_2.log main;
#error_log /var/log/nginx/error_2.log warn;
#↑これをコメントインするとdocker-composeで停止した状態になる。謎。
# 但し、docker restart ${work_id}-nginx をすると動く。後回し。
# また、access.logとerror.logにすると、なぜか記録されない。不思議。
EOS
#=====================
# uwsgi_paramsの作成
#=====================
cat <<EOS > ${workDirPath}/nginx/uwsgi_params
uwsgi_param QUERY_STRING \$query_string;
uwsgi_param REQUEST_METHOD \$request_method;
uwsgi_param CONTENT_TYPE \$content_type;
uwsgi_param CONTENT_LENGTH \$content_length;
uwsgi_param REQUEST_URI \$request_uri;
uwsgi_param PATH_INFO \$document_uri;
uwsgi_param DOCUMENT_ROOT \$document_root;
uwsgi_param SERVER_PROTOCOL \$server_protocol;
uwsgi_param REQUEST_SCHEME \$scheme;
uwsgi_param HTTPS \$https if_not_empty;
uwsgi_param REMOTE_ADDR \$remote_addr;
uwsgi_param REMOTE_PORT \$remote_port;
uwsgi_param SERVER_PORT \$server_port;
uwsgi_param SERVER_NAME \$server_name;
EOS
# uwsgiの設定ファイルを作成
cat <<EOS > ${workDirPath}/django/uwsgi.ini
[uwsgi]
socket = :81${work_id}
#socket = /DjangoContainer/uwsgi.sock
module = config.wsgi
#wsgi-file = /DjangoContainer/config/wsgi.py
#logto = /DjangoContainer/config/uwsgi.log
py-autoreload = 1
EOS
# djangoのコンテナが起動したときに実行するシェルファイルを作成
cat <<EOS > ${workDirPath}/django/start.sh
#!/bin/bash
django-admin startproject config .
uwsgi --ini /DjangoContainer/uwsgi.ini
EOS
docker-compose -f ${workDirPath}/docker-compose.yml up -d
(escを押して、:wqを押して保存して閉じる)
シェルスクリプトを実行して、Dockerを立ち上げる
// シェルファイルを実行(エラーが出ます)
$ bash ${workDirPath}/make1.sh
ERROR: Network shared declared as external, but could not be found. Please create the network manually using `docker network create shared` and try again.
// コレを実行すると、エラーが治ります。
$ docker network create shared
// Dockerを立ち上げる
$ docker-compose -f ${workDirPath}/docker-compose.yml up -d
// dockerの状態を確認する
$ docker ps -a
ブラウザからDjangoの表示を確認する
// ディレクトリ以下を一括でパーミッション変更
// Macで開発する場合は、これをやらない感じ
// yamutyaというユーザをMacで作っていなく、別ユーザでMacを利用しているため
// 同時に所有権が変更されたかも確認する
$ sudo chown -R $USER:$USER ${workDirPath}/django
$ sudo chmod -R g+w ${workDirPath}/django
$ sudo chown -R $USER:$USER ${workDirPath}/mysql
$ ls -l ${workDirPath}/django ${workDirPath}/mysql
// ${workDirPath}/mysql/data のディレクトリの所有者が元のままだった。なぜだ。
$ vim ${workDirPath}/django/config/settings.py
//(iで編集を開始する。)
//(↓該当部分をこのように変更する)
ALLOWED_HOSTS = ["*"]
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
//(↑該当部分をこのように変更する)
//(escを押して、:wqを押して保存して閉じる)
ブラウザからlocalhost、又はグローバルIPアドレスにアクセスして、Djangoのロケットの表示がされていたらOKです。
Lightsailで確認する場合は、ALLOWED_HOSTS = [“*"]をやっていないと、Djangoのエラーページが表示されます。但し、アスタリスクだと攻撃を受ける恐れがあるので、アスタリスクの代わりに独自ドメインを指定するほうが、セキュリティ的によいです。

ちなみにこの段階ではまだ、トップページは作成されていない状態です。
感想
LightsailのCentosでポート80がcloseのまま、dockerのnginxのコンテナを起動したら、ポート80は自動でopenになりました。iptablesもfirewalldもインストールしてません。つまり、LightsailのCentOSのデフォルト状態です。この状態でDockerのnginxを起動するだけで、ポート80をしっかりopenしてくれていました。
