面白法人カヤックさんのインターンで Sinatra + Nginx + MySQL を使った簡易イ〇スタを作りました!後日それをdocker-composeで動かそうとしたときに、docker-compose 周りで死ぬほどハマった上にあんまり解決策出てこず苦労しました。。。
備忘録がてらシェアです!
最終的なdocker-compose.yml
version: "3"
services:
web:
build: .
volumes:
- .:/app
ports:
- "4567:4567"
depends_on:
- db
command: bundle exec ruby myapp.rb -o 0.0.0.0
nginx:
image: nginx:latest
volumes:
- ./conf/nginx.conf:/etc/nginx/nginx.conf
- ./public:/var/www/html
ports:
- "8080:8080"
depends_on:
- web
db:
image: mysql:latest
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
MYSQL_DATABASE: "latestgram"
MYSQL_USER: "root"
volumes:
- ./sql:/docker-entrypoint-initdb.d
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
ports:
- "3306:3306"
1. コンテナ上でSinatraが動かない
状況
ローカル環境では(dockerのホストipがlocalhostの時)localhost:4567
でアクセスできるのですが、なぜかコンテナ上で動いている時にアクセスできない・・・
もちろんdocker-compose.yml
にポート解放の記述はあります。
解決策
docker-compose
の書き方が悪いのかと思って死ぬほどググりましたが、結局Sinatra側の仕様のようです。
Sinatraがデフォルトでは外部から繋がらなくなってたよ - Qiita
によると
なんとdevelopment環境だと、localhostからのアクセスしか受け付けないのがデフォルトらしい!!
とのこと。
じゃあdockerfileにCMD["bundle", "exec", "ruby", "myapp.rb"
**,"-o", "0.0.0.0"]
**とかdocker-compose.yml
にcommand: bundle exec ruby myapp.rb -o 0.0.0.0
すればいいのか!
・・・できない!!なぜだああああああ
myapp.rb内でset :bind '0.0.0.0'
する方法もあるらしいので試してみる。
・・・なぜか上手くいった!
なぜ上手くいかなかったんだ・・・?
2. 日本語を使う場合にMySQLの文字コードエラー
状況
ローカルのMacOSやWindows(WSL)では日本語を扱えるのに、docker-compose up すると
Incorrect string value: '\xE3\x81\x82' for column ...
とか
Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) for operation '='
が出る
解決策
デフォルトの文字コードを設定する必要があるそうです
MySQLのIllegal mix of collations (latin1_swedish_ci,IMPLICIT)のエラーについて - 文系プログラマによるTIPSブログ
docker-composeに
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
を追加しましょう。
そして、忘れてはいけないのがすでに起動しているMySQLコンテナを破棄してdocker-compose up
すること
こうしないと、変更前のコンテナ使ってしまうので同じエラー出ます
これに気づかずに2時間くらい消費したので、みなさんは私の屍を超えていってください・・・orz
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d1e9aac7bd1 hoge "bundle exec ruby my…" 10 minutes ago Up 10 minutes 0.0.0.0:4567->4567/tcp fugafuga
こんな感じで出てくるので、CONTAINER IDを参照して
docker rm 出てきたID
でいけます!
ちなみにdocker-compose.yml
内で自分で作成したDockerfile
がある場合は、Dockerfile
を編集した際にdockerイメージをbuildし直さないといけないので注意です。
docker-compose build
でいいと思います。
3. nginxやmysqlにdockerのホストIPを伝えたり、コンテナ経由でアクセス
WindowsではDocker Quickstart Terminal
を使っていて私の環境では192.168.99.100
でコンテナにアクセス出来ます。
しかしMacでDocker for Mac
などを使ってターミナル上で作業する場合はlocalhost
でのアクセスになります。
またnginxコンテナ→sinatraコンテナへアクセスする場合にはコンテナ通信用のipアドレスを割り当てないといけません。
mysql接続
docker-compose.yml
でmysqlコンテナのサービス名をdbにしているので、それを使ってアクセスできます!
def db_connect()
client = Mysql2::Client.new(
:host => 'db',
:port => '3306',
:username => 'root',
:password => '',
:database => 'latestgram',
:encoding => 'utf8mb4',
:datatbase_timezone => :local
)
return client
end
nginx.conf
同様に、Sinatraコンテナのサービス名webを使います。
また、dockerのホストipは$host
で設定可能です。(これに気づくのに苦労しました・・・)
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
upstream latestgram{
server web:4567;
}
server {
listen 8080;
server_name $host;
root /var/www/html;
proxy_set_header Host $host:8080;
proxy_set_header X-Forwarded-For http://latestgram:4567;
proxy_set_header X-Forwarded-Host $host:8080;
proxy_set_header X-Forwarded-Server $host:8080;
location / {
proxy_pass http://latestgram;
root /var/www/html;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
作ったもの
・・・というわけで作ったものはこちらです!
メンターの方がしっかりサポートしていただいて1週間で形にできました!
cloneしてdocker-compose up
で一発起動しますb