使用[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地址并粘贴到浏览器搜索栏即可)
请参考以下内容。