使用[Rails、AWS、Docker]在EC2上进行部署

這是一篇兼具備忘錄功能的文章。
作業系統:Amazon Linux 2

前提 – 一个前提

OR

前提条件 – 一个前提条件

我正在创建EC2实例,并在终端上进行SSH连接。
(该文章不涉及实例和RDS数据库的创建,但很多文章都有介绍,所以我认为那部分并不难。)

将本地环境的Rails应用程序转换为Docker容器化。

将nginx作为web服务器配置。将puma作为app服务器进行安装。

docker-compose.yml

Dockerfile

nginx_docker
  ├── Dockerfile
  └── nginx.conf

config
  └── puma.rb
FROM ruby:3.1.0

RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y yarn
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
RUN apt-get update -qq && apt-get install -y curl build-essential libpq-dev nodejs imagemagick chromium-driver 
ENV APP_PATH /myapp

RUN mkdir $APP_PATH
WORKDIR $APP_PATH
COPY Gemfile $APP_PATH/Gemfile
COPY Gemfile.lock $APP_PATH/Gemfile.lock
RUN bundle install

COPY . $APP_PATH
RUN yarn install

EXPOSE 3000

USER root

VOLUME /myapp/public
VOLUME /myapp/tmp

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
CMD /bin/bash -c "rm -f tmp/pids/server.pid && bundle exec rails s"
# nginx:1.22.1 イメージをdocker hubからインストールします。
FROM nginx:1.22.1

# インクルード用のディレクトリ内を削除
RUN rm -f /etc/nginx/conf.d/*

# Nginxの設定ファイルをコンテナにコピー
ADD nginx.conf /etc/nginx/conf.d/movie-review.conf

# ビルド完了後にNginxを起動
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

接下来是Puma的配置文件。
需要将”unix://#{app_root}/tmp/sockets/puma.sock”与nginx.conf中的server部分保持一致。

max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count

worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"

environment ENV.fetch("RAILS_ENV") { "development" }

pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }

plugin :tmp_restart

app_root = File.expand_path("..", __dir__)
# nginx.confのserverと一致させる。
bind "unix://#{app_root}/tmp/sockets/puma.sock"

stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true

将 Docker 容器上传至 AWS。

我将把本地的docker容器上传到创建的AWS实例上。需要连接到许多服务,例如ngix、puma和RDS。

在EC2上安装Docker。

我现在正在使用Amazon Linux 2。由于Amazon Linux 2023无法使用以下命令运行,所以需要使用其他命令。(我之前的文章中也有提到)
以下操作需要使用sudo。

$ amazon-linux-extras install docker -y
systemctl enable docker.service
systemctl start docker.service
curl -SL "https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-$(uname -s|tr [A-Z] [a-z])-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

我趁机也安装了 Git。

$ sudo yum install git

如果还有其他需要安装的东西,可以使用$ sudo yum install ○○来安装。

修改数据库.yml文件

由于直接输入用户名和密码不安全,我们使用环境变量来处理。

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV['DB_USER'] %>
  password: <%= ENV['MYSQL_PASSWORD'] %>
  host: <%= ENV['DB_HOST'] %>

development:
  <<: *default
  database: happylunch_development

test:
  <<: *default
  database: happylunch_test

production:
  <<: *default
  database: happylunch_production
  username: root
  password: <%= ENV['happylunch__DATABASE_PASSWORD'] %>

修改nginx.conf文件。

upstream myapp {
  server unix:///myapp/tmp/sockets/puma.sock;
}

server {
  listen 80;
  server_name localhost;

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  root /myapp/public;

  client_max_body_size 100m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;
  try_files  $uri/index.html $uri @myapp;
  keepalive_timeout 5;

  location @myapp {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://myapp;
  }
}

修改docker-compose.yml文件

version: "3"
services:
  db:
    image: mysql:8.0.31
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - 3306:3306
    platform: linux/x86_64/v8
  rails:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/myapp
      - public-data:/myapp/public
      - tmp-data:/myapp/tmp

    environment:
      TZ: Asia/Tokyo
      RAILS_ENV: development
      DB_HOST: db
      DB_USER: root
      MYSQL_PASSWORD: password
    ports:
      - "3000:3000"
    stdin_open: true
    tty:
      true
    depends_on:
      - db
  web:
    build:
      context: nginx_docker
    volumes:
      - public-data:/myapp/public
      - tmp-data:/myapp/tmp
    ports:
      - 80:80
    depends_on:
      - rails  

volumes:
  public-data:
  mysql-data:
  tmp-data:

定义环境变量

接下来,将环境变量的值写入到远程的database.yml文件中。

$ cd /movie-review/config
$ vi database.yml

主用户名和主密码存储在RDS的配置中,连接和安全性的端点被写明(尽管密码被掩盖,但在忘记时仍可更改密码)。

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: ******(マスターユーザー名)
  password: ******(マスターパスワード)
  host: ********ap-northeast-1.rds.amazonaws.com(エンドポイント)

如果进行了修改,请使用”:wq”命令保存。

接下来是Docker命令。如果没有权限,请在命令前加上”sudo”(例如:sudo docker-compose build)。

$ cd /movie-review

$ docker-compose build
//コンテナを作成します。

$ docker-compose up
//コンテナを起動します。

只要显示如下,启动就没有问题。

movie-review-rails-1  | * Listening on unix:///myapp/tmp/sockets/puma.sock
movie-review-rails-1  | Use Ctrl-C to stop

我将打开另一个终端。

$ cd /movie-review

$ docker-compose exec rails bash
//コンテナの中に入ります。

# bin/rails assets:precompile
//プリコンパイルを実施

# bin/rails db:create
//データベースを作成

# bin/rails db:migrate
//マイグレーションを実行

# bin/rails db:seed
//(必要であれば)

如果访问了http://固定IP(公共IP),应该能够正确显示。(只需复制EC2实例的公共IPv4地址并粘贴到浏览器搜索栏即可)

 

请参考以下内容。

 

bannerAds