/etc/ssh/sshd_config sudo vi
「Dockerベースの研究室クラウド基盤」の作成方法
JPA2022 TWS-004 「心理学研究における研究室インフラの整備」
Dockerベースの研究室クラウド基盤
サーバー設定
研究室クラウド基盤を整備するにあたって,以下のようにサーバーを設定する。
- さくらインターネットやGCPなどのサーバー上に,Dockerを使ってできるだけ楽にサービスを展開する(楽に設定したい)。
- traefikを通して,SSL,負荷分散などを行って,1つのサーバー上で複数のサービスを展開する(セキュリティは担保しつつサーバーは1つに抑えたい)。
注意事項
以降では各種サービスをサーバー上で展開して,研究室で活用していく方法について説明するが,以下の注意事項がある。
- 国里は臨床心理学者であり,情報系の専門家ではない。サーバーの利用については,各自がサーバーの基礎知識や基本的なセキュリティ管理をしっかり身につけていただくようにお願いします。
- 以降の内容について,誤った操作・設定による損害・損失について国里は責任を持てませんので,各自の判断で行ってください。
サーバーの選択
クラウドコンピューティングサービスは,GCP(Google Cloud Platform),AWS(Amazon Web Service),Microsoft Azure,さくらインターネット(専用サーバー)など様々ある。
VPSなどのサービスは安価だが,CPUの負荷がかかるRStudioやJupyterを使う場合はマシンパワーが足りないかもしれない(CPUに過負荷をかけてはいけないサービスもある)。国里は,2019年くらいからGCPを使っているが,2022年度からはゼミはさくらインターネットを使っている(円安の影響を受けない,固定金額)。
GCP(Google Cloud Platform)を用いたクラウド基盤の構築法
本日のデモの構成
GCPを使えるように設定し,GCE(Compute Engine)にて「インスタンスの作成」をクリックする。なお,Googleアカウントの2 段階認証を設定していない場合は,この機会に設定して,セキュリティを高める(パスワードも長く複雑性の高いものにしておく)。
今回は,月額の利用料金を低く抑えられるGCPのe2-medium(2vCPU, 4GB)を使う。複数人で使う場合は,n2-standard-2(2vCPU, 8GBメモリ,約75ドル/月),n2-standard-4(4vCPU, 8GBメモリ,約150ドル/月)が良いかもしれない(大体15名程度が在籍する国里研究室では,昨年度はn2-standard-4くらいを使っていた)。
ブートディスクを変更する
インスタンスを選んだら,「ブートディスク」で「変更」をクリックする。
OSやディスクの設定
OSはUbuntu 20.04 LTS,ディスクは50GBにした。
ファイヤーウォールを設定して,インスタンス起動
「HTTP トラフィックを許可する」と「HTTPS トラフィックを許可する」にチェックをいれて,「作成」をクリックする。インスタンスが作成されて起動される。
SSH接続してポートの変更をする
デフォルトの22番ポートには外部からの攻撃もあるのでポートを変更する。
ファイヤーウォールルールの追加
GCPの「VPCネットワーク」→「ファイヤーウォールルール」で「ファイアウォール ルールの作成」をクリックして,以下のように新しいSSHポートを設定する。
- 名前やターゲットタグ:任意(私は”ssh-allow-port”としています)
- 優先度:
1000
- トラフィックの方向:
上り
- 一致した時のアクション:
許可
- ソースのIP範囲:
0.0.0.0/0
- プロトコル:
tcp
- ポート: 好きなポート番号
GCP上でVMインスタンスをクリックし,「編集」ボタンを押して,ネットワークタグに上記で決めたターゲットタグを入れて保存する。
SSH接続してポートを変更する
インスタンスの「SSH」をクリックして,サーバーに接続(22番ポート仕様)する。
コンソールが出てきたら,以下のコマンドでsshdの設定ファイルを開く。
画面上で# Port 22
を探して, i
をタイプして(文字が入可能に),#
を削除して,22の代わりに使いたいポート番号を入力し,esc
キーをタイプしてから, :wq
とタイプする(保存&閉じる)。
sshdの設定を反映させるために,以下のコマンドでsshdを再起動させます。
sudo systemctl restart sshd
22ポートを閉じる
22番portで開いた画面は閉じずにそのままにし(もしここで閉じちゃうと,ポート設定がうまくできてない場合に自分がサーバーにアクセスできなくなる),VMインスタンスの「SSH」の下矢印を押して,「ブラウザウィンドウでカスタムポートを開く」をクリックする。そして,入力欄に先程設定した新しいSSHポート番号を入力する。
新しいSSHポートでも開けたら,「VPCネットワーク」→「ファイヤーウォールルール」で「ファイアウォール ルールの作成」を押して,以下を設定する。
- 名前やターゲットタグ: 任意(私は”disallow-ssh22”とした)
- 優先度:
1000
- トラフィックの方向:
上り
- 一致した時のアクション:
拒否
- ソースのIP範囲:
0.0.0.0/0
- プロトコル:
tcp
- ポート:
22
VMインスタンスの「編集」を押し,ネットワークタグに上記で決めたターゲットタグを入れて保存する(これで,httpのタグ,httpsのタグ,新しいsshポートのタグ,22番ポートを閉じるタグの4つになる)。
通常のSSH接続(22番ポート)をしても接続できず,「ブラウザウィンドウでカスタムポートを開く」で自分で設定したポートを使ってSSH接続できたら成功になる。
SSH接続後に以下を入力するとアクセス状況が見れる( f
で次の画面に進んで, q
で閉じます)
/var/log/auth.log sudo less
その他のセキュリティ設定としては,(1)請求アラートの設定(不正利用にも気付ける),(2)サーバー稼働状況の監視,(3)GCPのスマホアプリをいれていつでもVMをシャットダウンできるようにしておくなどがある。
Domainの入手とサブドメインの設定
Google Domainなどで研究室サーバー用のドメインを入手する(年1400円程度,無料でも入手できるサービスもあるが,国里は利用したことがない)。
Google Domainなどで,DNS設定をする(ドメイン名とIPアドレスを紐付ける)。ホスト名にサービス名をいれるとサブドメイン化できる(データにはインスタンスで表示される「外部IP」を入れる)。
Dockerのインストール
サーバー自体の設定ができたので,サービスを動かすためのDockerをDocker社のドキュメントに従ってインストールする。
まず,以下のように,Dockerのインストールに必要なソフトをインストールする。
-get update
sudo apt-get install ca-certificates curl gnupg lsb-release sudo apt
GPGキーの追加とリポジトリの用意をする。
-p /etc/apt/keyrings
sudo mkdir -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
curl "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null echo
Docker Engineをインストールする。これでDockerの準備は完了になる。
-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin sudo apt
Traefikの準備
各種サービスの暗号通信化(SSL)などをするTraefikをDockerを使って準備する。
Traefikはダッシュボードを出してくれるが,外部から丸見えなので,パスワードをつけるBASIC認証で使うと良い。その際に,htpasswdというソフトを使うので,それが入ったapache2-utilsをインストールする。
-utils sudo apt install apache2
htpasswdを,ユーザー名とパスワードを変更して実行する。アカウント名とハッシュ値が出てくるので保存しておく。
-nb ユーザー名 パスワード htpasswd
dockerでネットワークの準備をする(ここでは,traefik-networkという名前にして,後でも使う)。
-network sudo docker network create traefik
Traefikの作業フォルダを作って,移動する。
mkdir traefik cd traefik
以下を実行して,traefik.ymlを用意する。
sudo vi traefik.yml
以下をコピペして,メールアドレス@example.comはご自身のメールアドレスに変更する。変更できたら, esc
を押して,:wq
をタイプすることで保存して閉じる。
なお,以降でも,このymlが出てくるが,ymlはインデントが重要なので,インデントがズレていると正常に動作しない。ymlでのインデントは,半角スペース2つになる。
:
entryPoints:
web: :80
address:
http:
redirections:
entryPoint: websecure
to: https
scheme:
websecure: :443
address:
api: false
insecure: true
dashboard
:
providers:
docker: false
exposedByDefault
:
certificatesresolvers:
myresolver:
acme:
httpChallenge: web
entryPoint: "メールアドレス@example.com"
email: "/letsencrypt/acme_myresolver.json"
storage
:
log: "/logs/traefik.log"
filePath: json
format: INFO
level
:
accessLog: "/logs/access.log"
filePath: json format
以下を実行して,compose.yml を用意する。
sudo vi compose.yml
以下をコピペする。your.domainは,自分の使っているドメイン名に変更し, アカウント名とハッシュ値を貼り付けは,上のhtpasswdで出たIDのハッシュ値に変更する(その際に, $は全て$$にしないと動かない落とし穴があるので注意する。これでミスると動かない)。できたら,esc
を押して,:wq
をタイプすることで保存して閉じる。
:
services:
traefik: traefik:latest
image: traefik
container_name: always
restart:
ports- "80:80"
- "443:443"
:
networks- traefik-network
:
environment: Asia/Tokyo
TZ:
labels: true
traefik.enable: Host(`traefik.your.domain`)
traefik.http.routers.dashboard.rule: websecure
traefik.http.routers.dashboard.entrypoints: myresolver
traefik.http.routers.dashboard.tls.certresolver: api@internal
traefik.http.routers.dashboard.service: auth
traefik.http.routers.dashboard.middlewares: アカウント名とハッシュ値を貼り付け
traefik.http.middlewares.auth.basicauth.users:
volumes- letsencrypt_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- /var/log:/logs
:
volumes:
letsencrypt_data
:
networks-network:
traefik: true external
compose.ymlを以下のように実行する。これで,compose.ymlで設定したようにdockerが設定され,コンテナが起動する。
-d sudo docker compose up
https://traefik.ご自身のドメイン にアクセスすると,アカウント認証があるが,設定したものを入力して,以下のようなダッシュボードがでてきたら,成功している。
問題がなさそうなら,一度ホームディレクトリに戻る。
cd ..
RStudio serverを用意する
ホームディレクトリ内にrstudio_composeディレクトリを作って,そちらに移動し,compose.ymlを作る。
sudo mkdir rstudio_compose
cd rstudio_compose sudo vi compose.yml
開いたdocker-compose.ymlに,以下のコードをコピペして,以下の変更を加える。
- rstudio.your.domainのyour.domainを自分のドメイン名に変更
- environmentのユーザーIDとパスワードを自分のものに変更
変更できたら,esc
キーをタイプして, :wq
とタイプする(保存して閉じる)。
:
services:
rstudio: ykunisato/paper-r:latest
image: rstudio
container_name:
networks- traefik-network
: rstudio
container_name: always
restart:
environment- USER=ユーザー名
- PASSWORD=パスワード
:
volumes- ./rstudio:/home/rstudio
:
labels: true
traefik.enable: Host(`rstudio.your.domain`)
traefik.http.routers.rstudio.rule: websecure
traefik.http.routers.rstudio.entrypoints: myresolver
traefik.http.routers.rstudio.tls.certresolver
:
networks-network:
traefik: true external
以下を実行して,compose.ymlに従ってコンテナを起動する。イメージのダウンロードなどにしばらく時間がかかる。doneとでてきたら終了。
-d sudo docker compose up
https://rstudio.ご自身のドメイン にアクセスして,RStudioのログイン画面が出てきて,ログインができたらうまくいっている。
一度,ホームディレクトリに戻る。
cd ..
ここでうまくいかない場合,volumesの左側の./rstudioは,.のところをGCP上でpwdをした時にでてくるカレントディレクトにする必要があるかもしれない。また,RStduioの方の修正でうまくいかない場合は,上のTraefikの設定にミスがないかチェックください。
RStudioへのユーザー追加
compose.ymlで設定した以外のユーザーを追加する場合は,Dockerコンテナに接続してユーザーアカウントを作る。まず,以下のコマンドで,rstudioコンテナにssh接続する。
-it rstudio bash sudo docker exec
次に,以下のコマンドで新規ユーザー登録する。パスワードを聞かれるので打ち込んで,あとはエンターキーやYをタイプする。
sudo adduser 新規ユーザー名
このままだと,各ユーザーが自由にRパッケージをいれられないので,以下のコマンドで,ユーザーをstaffグループにする。
-a -G staff ユーザー名 sudo usermod
exitでコンテナから出る。
exit
ユーザーの一括追加
上記の方法は1名ずつ追加する方法だが,人数が多くなると大変になる。その場合は,newusersを使った一括登録が良い。まずは,以下のような感じの情報を表計算ソフトに入力する。ユーザーごとに変更が必要なのは,ユーザー名,ユーザーID(1001から連番にする),パスワード,ホームディレクトリ名(home/rstudioの下にユーザー名をいれる)である。残りの,グループID(50), フルネーム(空白),ログインシェル(/bin/sh)は全員同じで問題ない。
ユーザー名 | パスワード | ユーザーID | グループID | フルネーム | ホームディレクトリ | ログインシェル |
---|---|---|---|---|---|---|
ユーザー1 | ユーザー1のパスワード | 1001 | 50 | /home/rstudio/ユーザー1 | /bin/sh | |
ユーザー2 | ユーザー2のパスワード | 1002 | 50 | /home/rstudio/ユーザー2 | /bin/sh | |
ユーザー3 | ユーザー3のパスワード | 1003 | 50 | /home/rstudio/ユーザー3 | /bin/sh |
なお,上記の情報は,最終的に区切りに:を使って保存する。つまりuser1については,ユーザー1:ユーザー1のパスワード:1001:50::/home/rstudio/ユーザー1:/bin/shになる。上記の情報を表計算ソフトにいれて,それをcsvファイルで出力して,テキストエディタで開いて,カンマを:に変換して,一番上のヘッダー情報は削除して,最後に.txtの拡張子で保存するのが楽かと思う。ファイル名は,user.txtとしておく(なんでもいい)。
user.txtが作成できたら,VMにSSH接続して,user.txtをアップロードする(ウィンドウの右上の設定っぽいボタンをクリックするとアップロードの選択肢がでてくる)。アップロードしたuser.txtをrstudioのフォルダに一時的に移動する。
/rstudio sudo mv user.txt rstudio_compose
rsutdioのコンテナに入る。
-it rstudio bash sudo docker exec
以下を実行して,一括でユーザー登録する。
/home/rstudio/user.txt newusers
一応,user.txtを削除してから,コンテナからでる。
/home/rstudio/user.txt
rm exit
JupyterHubを用意する
ホームディレクトリ内にjupyterhub_composeディレクトリを作って,そちらに移動し,compose.ymlを作る。
mkdir jupyterhub_compose
cd jupyterhub_compose sudo vi compose.yml
以下をコピペして,jupyterhub.your.domainのyour.domainを自分のドメイン名に変更する。変更できたら,esc
キーをタイプして, :wq
とタイプする(保存して閉じる)。
:
services:
jupyterhub: ykunisato/ccp-lab-hub
image: jupyterhub
container_name:
networks- traefik-network
: always
restart:
volumes- /home/ubuntu/jupyterhub:/home
:
labels: true
traefik.enable: Host(`jupyterhub.your.domain`)
traefik.http.routers.jupyterhub.rule: websecure
traefik.http.routers.jupyterhub.entrypoints: myresolver
traefik.http.routers.jupyterhub.tls.certresolver
:
networks-network:
traefik: true external
以下を実行して,compose.ymlに従ってコンテナを起動する
-d sudo docker compose up
特にエラーが出てないなら,一度ホーム画面に戻る
cd ..
Jupyter Hubのユーザー追加と設定
利用開始にあたり,コンテナ内に入ってユーザーを追加する(XXXはユーザー名,途中でパスワードが聞かれる。あとはYを打ったりエンターを押す)。
-it jupyterhub bash
sudo docker exec adduser XXX
作成したアカウントをsuにして,juliaを起動する。
su XXX julia
以下をコピペして,juliaを設定する(パッケージを一気にインストールする)。
"PYTHON"] = "";using Pkg;Pkg.update(); Pkg.add(["IJulia","PyCall"]); Pkg.build(["IJulia","PyCall"]); Pkg.add(["DataFrames","PyPlot","Distributions","Statistics","JuliaFormatter","CPUTime","Gadfly","GLM","Optim","Plots","Query","RDatasets","SpecialFunctions","StatisticalRethinking","StatsBase","StatsFuns","StatsPlots","AdvancedHMC","BAT","Bijectors","CmdStan","DiffEqBayes","DistributionsAD","ForwardDiff","MCMCChains","MeasureTheory","ParameterizedFunctions","Turing","LinearAlgebra","DifferentialEquations","Roots","SymPy","ForneyLab"]);Pkg.precompile() ENV[
exitでコンテナから出る。
exit
https://jupyterhub.ご自身のドメイン にアクセスして,Jupyterhubのログイン画面が出てきて,ログインができたらうまくいっている。
JATOSを用意する
ホームディレクトリ内にjatos_composeディレクトリを作って,そちらに移動し,compose.ymlを作る。
sudo mkdir jatos_compose
cd jatos_compose sudo vi compose.yml
以下をコピペして,jatos.your.domainのyour.domainを自分のドメイン名に変更する。変更できたら,esc
キーをタイプして, :wq
とタイプする(保存して閉じる)。
:
services:
jatos: jatos/jatos:latest
image: jatos
container_name:
networks- traefik-network
: always
restart:
labels: true
traefik.enable: Host(`jatos.your.domain`)
traefik.http.routers.jatos.rule: websecure
traefik.http.routers.jatos.entrypoints: myresolver
traefik.http.routers.jatos.tls.certresolver
:
networks-network:
traefik: true external
以下を実行して,compose.ymlに従ってコンテナを起動する。
-d sudo docker compose up
エラーが無ければ,一度ホーム画面に戻る
cd ..
JATOSは立ち上がったらすぐに,https://jatos.ご自身のドメイン にアクセスして,admin/adminでログインして,アドミンのパスワードを変更する(最初は誰でもadmin/adminで入れるので,立ち上がったらすぐに設定する)。あとの設定はJATOS上でできる。
WordPressを用意する
ホームディレクトリ内にwordpress_composeディレクトリを作って,そちらに移動し,compose.ymlを作る。
sudo mkdir wordpress_compose
cd wordpress_compose sudo vi compose.yml
以下をコピペして,以下を変更する。
- wordpress.your.domainのyour.domainを自分のドメイン名に変更
- ルートのパスワードをご自身のものに変更
- DBのパスワードをご自身のものに変更(2箇所)
変更できたら,esc
キーをタイプして, :wq
とタイプする(保存して閉じる)。
:
services:
db: mysql:5.7
image: wp-db
container_name:
volumes- db_data:/var/lib/mysql
:
networks- default
: always
restart:
environment: ルートのパスワード
MYSQL_ROOT_PASSWORD: wordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: DBのパスワード
MYSQL_PASSWORD
:
wordpress:
depends_on- db
: wordpress:latest
image: wordpress
container_name:
networks- traefik-network
- default
: always
restart:
environment: db:3306
WORDPRESS_DB_HOST: wordpress
WORDPRESS_DB_USER: DBのパスワード
WORDPRESS_DB_PASSWORD:
labels: true
traefik.enable: Host(`wordpress.your.domain`)
traefik.http.routers.wordpress.rule: websecure
traefik.http.routers.wordpress.entrypoints: myresolver
traefik.http.routers.wordpress.tls.certresolver
:
volumes:
db_data
:
networks-network:
traefik: true external
以下を実行して,compose.ymlに従ってコンテナを起動する
-d sudo docker compose up
エラーが無ければ,ホーム画面に戻る
cd ..
https://wordpress.ご自身のドメイン にアクセスして, WordPressが立ち上がったのを確認したら,WordPressのインストールとアドミンアカウントの設定を行う。
プラグインのSensei-LMSをインストールして,有効化する。
サービスの稼働状況の確認
これで,自分のサーバーで4サービス(RStudio server, JupyterHub, JATOS, WordPress)が展開できた。以下で稼働状況が確認できる。
-a sudo docker ps
各サービスの使用状況(CPUやメモリ)は,以下で確認できる。使用状況が流れるので,不要になったら,Ctrl
+ c
で停止する。使ってないのに異常にCPUが稼働している場合は,なんらかのトラブルを想定する。
-a sudo docker stats
Enjoy!