Rails,nginx,mysqlでDocker環境で構築する

# Version
 ruby 2.5.7
 rails 5.2.8
# 構成
```console:フォルダ構成
RailsProject
├── mysql
│ 
├── nginx
│   ├── Dockerfile
│   ├── default.conf
│ 
├── rails
│   ├── Dockerfile
│   ├── Gemfile
│   ├── Gemfile.lock
│
├── static 
│   ├── index.html
│
└── docker-compose.yml
```
全体イメージ
![全体イメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/2fee4e6d-612f-4049-a3e2-f2909016ea79.png)


## STEP1_ブラウザからNGINXへアクセス
![ブラウザ経由でNGINXに接続.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/86677936-6b0a-48a9-bc47-6050faa2e0b4.png)
### １．プロジェクトフォルダにnginxフォルダを作成し、Dockerfileを作成します
```console:bash
$mkdir nginx
$cd nginx
nginx$ touch Dockerfile
```
### ２．Dockerfileを確認
```console:Dockerfile
# (1)ベースイメージとして軽量のNginxイメージを使用
FROM nginx:alpine

# (2)ローカルのdefault.confファイルをNginxの設定ディレクトリにコピー
COPY ./default.conf /etc/nginx/conf.d/default.conf
```
(1)軽量のNGINXをベースとして使います。
(2)設定ファイル(default.conf)をコンテナ内の/etc/nginx/cof.dディレクトリへコピーします。

### ３．DockerfileからイメージをビルドしNGINXコンテナを起動します
```console:bash
# ビルド
nginx$ docker build -t nginx .

# イメージ一覧を確認
nginx$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    93f9c72967db   6 weeks ago   47MB

# nginxコンテナを起動
nginx$ docker run -d -p 8888:80 nginx
```
### ４．ブラウザからNGINXにアクセスできるか確認します

ブラウザでhttp://localhost:8888/にアクセスします。
このように表示されれば接続は成功です。
![スクリーンショット 2025-01-13 050016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/b6472d12-1225-a6b4-be50-bd36d7c8e2c4.png)




## STEP2_NGINXを介してRailsにアクセスします
![nginxとrailsの連携.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/245c12f7-5140-42ab-9715-516a79ca4721.png)

### １．プロジェクトフォルダにdocker-compose.ymlファイル、<br> railsフォルダにDockerfile・Gemfile・Gemfile.lockを作成します。
```console:bash
$touch docker-compose.yml
$mkdir rails
$cd rails
rails$ touch Dockerfile
rails$ touch Gemfile
rails$ touch Gemfile.lock
```
### ２．Gemfileの設定
```console:Gemfile
source 'https://rubygems.org'
gem 'rails', '5.2.8'
```
※Gemfile.lockは空で問題ありません

### ３．Dockerfileの設定
```console:Dockerfile
# ベースにするイメージを指定
FROM ruby:2.5.7

# RailsのインストールやMySQLへの接続に必要なパッケージをインストール
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs default-mysql-client vim

# rubygemsの更新
RUN gem update --system 3.2.3

# コンテナ内にappディレクトリを作成
RUN mkdir /app

# 作成したmyappディレクトリを作業用ディレクトリとして設定
WORKDIR /app

# ローカルの Gemfile と Gemfile.lock をコンテナ内のmyapp配下にコピー
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock

# コンテナ内にコピーした Gemfile の bundle install
RUN bundle install

# ローカルのmyapp配下のファイルをコンテナ内のmyapp配下にコピー
COPY . /app
```




### ４．docker-compose.ymlの設定
```console:docker-compose.yml
version: '3'

services:
  nginx:
    build:
      context: ./nginx
    ports:
      - "80:80"
    depends_on:
      - web  # Nginxがwebに依存して起動
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf  # Nginx設定ファイルの追加
  web:
    build:
      context: ./rails
    command: bash -c 'rm -f /app/tmp/pids/server.pid && rails server -b 0.0.0.0'
    volumes:
      - ./rails:/app
    ports:
      - "3000:3000"
    depends_on:
      - db

  db:
    image: mysql:5.7

    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: app_db
    ports:
      - "3306:3306"
    volumes:
      - ./mysql/volumes:/var/lib/mysql


```







### ２．default.confの設定
```console:default.conf
#Nginxサーバ設定
server {
  # (1)ポート80で待ち受けし、localhostというホスト名でアクセスされる
  listen 80;  
  server_name localhost;  

　#/ルートに対するリクエストの処理方法
  location / {
    # (2)Nginxが受け取ったリクエストをhttp://web:3000にプロキシ
    proxy_pass http://web:3000; 

    # (3)クライアント情報をバックエンドサーバへ転送
    proxy_set_header Host $host;  # クライアントのホスト名を設定
    proxy_set_header X-Real-IP $remote_addr;  # クライアントのIPアドレスを設定
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # クライアントの元のIPアドレスを設定
    proxy_set_header X-Forwarded-Proto $scheme;  # プロトコル（httpまたはhttps）を設定
  }
}

```
(1)localhostというホスト名でアクセスされポート80で待ち受けします。
(2)Nginxが受け取ったリクエストをhtttp://web:3000にプロキシします。
　この設定でNginxからRailsに連携されます。
 　[web]は後述するdocker-compose.ymlで指定したサービス名を指定してください。
(3)クライアント情報をバックエンドサーバへ転送します。
　設定内容はホスト名・IPアドレス・通信プロトコル





### ３．rails newでプロジェクトファイルの生成
railsの雛形をつくりGemfileを更新します。
```console:bash
$ docker-compose run web rails new . --force --database=mysql --skip-bundle
```

### ３．database.ymlの設定
### ４．ビルドを実行し更新されたGemをインストールします。
```console:bash
$ docker-compose build
```
### ５．コンテナを起動します。
```console:bash
$ docker-compose up -d
```
docker-compose psコマンドで起動中のコンテナを確認します。
```console:bash
$ docker-compose ps
   Name                 Command               State                    Ports                  
----------------------------------------------------------------------------------------------
rp-nginx-1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:80->80/tcp,:::80->80/tcp        
rp-web-1     bash -c rm -f /app/tmp/pid ...   Up      0.0.0.0:3000->3000/tcp,:::3000->3000/tcp
```
### ６．ブラウザからrailsにアクセスします。
ブラウザでhttp://localhost:3000/にアクセスします。
Mysqlの設定をしてないので現時点ではこのように表示されれば接続は成功です。
![web1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/7bc65386-3a84-8ef2-9d73-154c8cfb465d.png)

### 7．DBCreateでデータベース作成。
```console:bash
$ docker-compose run web rails db:create
```





### ８．Unicon設定
１．Gemfileにunicorn追加
２．rails/configにunicorn.rbの追加
３．ymlファイルに以下を追加
command: bash -c 'rm -f /app/tmp/pids/server.pid && bundle exec unicorn -c config/unicorn.rb -E development -D'
-Dでバックグラウンドで稼働させるとフォアグラウンドで動作するプロセスがなくエラーで落ちる
４．nginxの設定ファイルを編集
５．コンテナの停止後、ビルドして再度コンテナを起動


docker-compose run web rails new . --force --no-deps --database=mysql
docker-compose run: Docker Composeで新しいコンテナを一時的に実行します。

web: 実行するサービスの名前（この場合はwebサービス）。

rails new: Railsのコマンドで、新しいRailsアプリケーションを作成します。

.: 現在のディレクトリに新しいRailsアプリケーションを作成します。
DockerファイルのWORKDIRで指定したパスがカレントディレクトリとなる

--force: 既存のファイルがあっても上書きします。

--no-deps: 依存サービスを起動せずに、このサービスだけを実行します。

--database=mysql: データベースとしてMySQLを使用するように設定します。


------------------------------------------------------------------------
docker-compose build
ymlに記載されたサービス全てに対してビルドを行う

docker-compose up
コンテナ起動

docker-compose logs web
ログを確認


----------------------

docker ps
dockerの起動状態を確認

■Dockerfile
 RUN ビルド時に実行
 CMD コンテナ起動時に実行

■yml
 command コンテナ起動時に実行。DockerfileのCMDを上書きする

■ビルドコンテキスト
　docker buildコマンドで指定したディレクトリ配下のファイル・ディレクトリが
  dockerfileからのアクセス対象となる

  /home/userでdocker build .とすると/home/user内のファイル・ディレクトリ
  がビルドコンテキストとなる

  dockercompose.ymlでビルドコンテキストを指定する場合は、ymlファイルからの相対パスで指定する



作業
database.yamlの変更


トラブルシューティング

1. UnicornのPIDファイルの問題
原因: 既存のPIDファイルが残っていたため、Unicornが起動できなかった。

対策: Dockerfileに、古いPIDファイルを削除するコマンドを追加。

3. データベースエラー ("Unknown database 'app_development'")
原因: 指定されたデータベースが存在しなかった。

対策: データベースを作成。

# Dockerコマンド

dockerイメージのリストを表示する
```console:
docker image ls
```
コンテナのリストを表示する
```console:
docker container ls -a
```

未使用のイメージを一括削除
```console:
docker image prune
```
未使用のイメージを一括削除(tag付のイメージも含めて)
```console:
docker image prune -a
```
イメージを削除
```console:
docker image rm mysql:5.7
```
イメージをビルド
```console:
docker build [ -t ｛イメージ名｝ [ :｛タグ名｝ ] ] ｛Dockerfileのあるディレクトリ｝
```
稼働中のコンテナを表示
```console:
docker ps
```

コンテナの起動
```console:
docker start 
```
コンテナの作成・起動
```console:
docker run 
```
コンテナ内でコマンドを実行
```console:
docker-compose run web bash
```

停止コンテナを一括削除
```console:
docker container prune
```


# メモ
unicornの設定はrails new の後
database.yml編集前に権限の変更
```console:
rails$ sudo chown -R $USER:$USER .
```

mysqlログイン
mysql -u root -p

db表示
mysql> SHOW DATABASES;

dbの環境変数を確認
docker exec -it rp_db_1 env

コンテナ起動　-dはバックグラウンドで起動
docker-compose up -d

dbコンテナを起動
docker exec -it rp_db_1 bash

dbボリュームの削除
https://qiita.com/hanyuTransfer/items/4584d0a4d85f0f78cfb6
既存のDBが存在する場合、設定した変数は反映されない
⇒既存のDBを削除してからビルドしなおす
sudo rm -rf ./mysql/volumes/*