Deploy 1 app Ruby on Rails bằng AWS AppRunner
Xin chào các bạn. Lâu lắm mới lên bài có làm hands-on.
Gần đây do công việc cá nhân nên mình đã thử khá nhiều cách deploy trên AWS. Và hiện thì mình đã deploy thành công trên AWS AppRunner với khá nhiều thứ phải config nên muốn viết lại chia sẻ cho các bạn. Đó là lý do bài viết này sinh ra.
Giới thiệu về AWS AppRunner
AWS App Runner là một dịch vụ ứng dụng bộ chứa được quản lý toàn phần cho phép bạn xây dựng, triển khai và chạy các ứng dụng web cũng như dịch vụ API được đưa vào container mà không cần có cơ sở hạ tầng hoặc kinh nghiệm về container trước đó.
Nôm na các bạn sẽ không cần quan tâm tới infra, chỉ cần build 1 cái docker image thật chuẩn rồi đưa lên là xong.
Còn về giá cả thì khá rẻ, nhưng không nằm trong Free Tier 😂😂😂
Tổng quan hệ thống sẽ làm
Sau khi dựng hệ thống và xem lại thì đây là hệ thống mình đã triển khai thành công:
Các bước chuẩn bị cho phía local
Setup project Ruby on Rails
Bước đầu tiên chúng ta cần làm là chuẩn bị 1 Dockerfile:
FROM ruby:3.1.2
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -\
&& echo 'deb http://dl.yarnpkg.com/debian/ stable main' > /etc/apt/sources.list.d/yarn.list
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash -
RUN apt-get update -qq && apt-get install -y nodejs build-essential postgresql-client yarn \
curl dirmngr apt-transport-https lsb-release ca-certificates
WORKDIR /rails-lyrics-site
COPY Gemfile /rails-lyrics-site/Gemfile
COPY Gemfile.lock /rails-lyrics-site/Gemfile.lock
RUN bundle install
COPY . /rails-lyrics-site
RUN mkdir -p tmp/sockets
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
VOLUME /rails-lyrics-site/public
VOLUME /rails-lyrics-site/tmp
CMD bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
EXPOSE 3000
Ở bên trên, ngoài các thao tác lq tới file entrypoint chúng ta sẽ thiết lập sau thì chúng ta cần định nghĩa volume tmp và public, đồng thời phía dưới mở port 3000 để container đọc được
Nội dung của entrypoint.sh
#!/bin/bash
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid
if [ "$RAILS_ENV" = "production" ]; then
bundle exec rails assets:precompile
bundle exec rails db:create
bundle exec rails db:migrate
fi
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
Và cuối cùng là file docker-compose.yml
:
version: '3'
services:
app-runner:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/rails-lyrics-site
- bundle:/usr/local/bundle
- tmp-data:/rails-lyrics-site/tmp
- public-data:/rails-lyrics-site/public
ports:
- "3000:3000"
volumes:
bundle:
tmp-data:
public-data:
Tại sao ở đây mình chỉ dùng duy nhất 1 container và không dùng container nào khác? Well, AppRunner chỉ cho chạy 1 container và nếu mình tạo file như chạy local thông thường thì lúc deploy sẽ bị báo không tìm thấy container phụ thuộc dẫn tới deploy hỏng.
Sau đó thì theo các bước tạo Gemfile
, Gemfile.lock
, khởi tạo project như ở bài Tạo project Rails 6 với PostgresSQL 11 bằng Docker (bài hơi cũ, Rails version cũng cũ nhưng mà cách làm vẫn y hệt), chúng ta sẽ có 1 project Rails 7
Setup database và assets compile
# config/database.yml
default: &default
adapter: postgresql
encoding: unicode
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
production:
<<: *default
database: lyrics_site_production
host: <%= ENV["DB_HOST"] %>
username: <%= ENV["DB_USERNAME"] %>
password: <%= ENV["DB_PASSWORD"] %>
Setup database như trên bởi các bạn chỉ cần 1 database cho hệ thống, còn host, username và password để connect tới database server sẽ không cố định và là thông tin cần bảo mật nên ta sẽ dựa vào biến môi trường.
Tiếp đó, chúng ta sửa ở config/environments/production.rb
như sau:
config.assets.compile = true
Về cơ bản ta đã thiết lập xong phía local.
Các bước chuẩn bị cho phía AWS
Trước khi vào bước đầu tiên thì phần này mình cứ giả sử các bạn có tài khoản AWS rồi để bài có thể đi vào nội dung chính nhất có thể
Tạo 1 ECR
Phần này là phần tạo đơn giản, vào màn hình quản lý ECR, chọn "Create Repository" và nhập tên vào là xong
Sau khi tạo xong, các bạn nhớ hãy push image vừa được tạo phía lên ECR repository mới tạo
Tạo RDS
Đây là phần cơ bản với AWS nên mình cũng xin chỉ nêu ra. Các bước cụ thể các bạn cứ làm như bình thường. Kết quả cuối cùng đã che là đây:
Nhân tiện đừng thấy cái AZ mình dùng và ảnh có che ở trên mà có những suy nghĩ mở rộng nhé các bạn 😂😂😂
Deploy
Đầu tiên, vào AppRunner, bấm Create Service và màn hình hiện ra:
Mục Container image URI thì điền URI của ECR mới tạo bên trên, ví dụ: xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/lyrics-site-app-runner:latest
Mục Deployment Setting, chọn như sau:
ECR access role ở đây mình đã từng tạo rồi nên dùng luôn cái đã tạo. Các bạn chọn Create new role cũng không vấn đề gì.
Còn deploy thì mình xác định là deploy tạm và Automatic deploy tốn tiền nên mình chọn Manual
Sang trang tiếp theo:
Các bạn điền service name tuỳ ý, tự setup Virtual CPU và Virtual memory theo nhu cầu
Phần Environment Variables các bạn điền các biến sau
Để kết nối với database, các bạn vào Networking, custom như dưới:
VPC, Subnets, SecurityGroups là thông tin của phía RDS.
Sau đó các bạn deploy và trang web trống sẽ hiện ra. Bước tiếp theo bạn hãy import 1 chút data vào database mới tạo ở RDS.
Và đây là sản phẩm sau khi deploy và import data. Hãy chú ý tới domain gạch đỏ: https://hmmhmdmsb7.ap-northeast-1.awsapprunner.com
Các bạn cũng có thể custom domain hay gì đó vì trong AppRunner cũng có option này
Kết bài
Mình có để lại branch mình đã làm để các bạn tham khảo: https://github.com/BlazingRockStorm/rails-lyrics-site/tree/app-runner. Các bạn clone branch này về và thử deploy nếu có hứng thú nhé.
- P/s: Các bạn nên deploy thử chứ link trên kia mình sẽ tắt và xoá trong vì đây chỉ là deploy thử nghiệm của mình. Mình không có ý định dùng nó lâu dài
Tham khảo
All rights reserved