- vừa được xem lúc

Deploy một ứng dụng rails đơn giản với Docker

0 0 47

Người đăng: Dat Nguyen

Theo Viblo Asia

Như chúng ta đã biết docker compose là công cụ tuyệt vời để deploy các ứng dụng Ruby Rails. Nó cho phép chúng ta có thể dễ dàng tách biệt các môi trường ruby, database hay thậm chí là Redis. Trong bài viết này chúng ta sẽ thực hiện các bước để deploy một ứng dụng rails lên heroku sử dụng docker bao gồm:

  • Setting một app rails trong docker compose
  • Run các tác vụ cần thiết như cài đặt gem, migration
  • Deploy lên heroku

1. Setting rails app với docker

Tạo một thư mục bằng cách chạy câu lệnh như sau:

$ mkdir -p ~/myapp/rails-compose
$ cd ~/myapp/rails-compose

Sau khi đã tạo xong thư mục, ta sẽ tạo một file Dockerfile với nội dung như sau:

FROM ruby:alpine RUN apk add --update build-base postgresql-dev tzdata

Giải thích các câu lệnh trên:

  • FROM ruby:alpine câu lệnh này để ta sẽ lấy image Ruby mới nhất. Alpine linux là một base image nhỏ hơn
  • RUN apk add --update ...
  • build-base là gói chứa những tool cần thiết để complile từ source
  • postgresql-dev gói được sử dụng để cài đặt gem pg
  • tzdata được sử dụng bởi rails cho timezome Tiếp đến ta sẽ tham chiếu Dockerfile này từ một file docker-compose.yml
version: '3.6' services: web: build: .

Khi sử dụng build . nó sẽ hiểu là có một Dockerfile nằm trong thư mục. Nó cũng sẽ sử dụng thư mục hiện tại khi build một image
Sau khi chúng ta tạo xong file này, có thể thử chạy

$ docker-compose build web

Nó sẽ pull image Ruby alpine và cài đặt các dependencies trên đó
Tiếp theo chúng ta cần init một project sử dụng câu lệnh rails new. Để làm điều đó ở bên trong container chúng ta cần mount những file local trong hệ thống vào bên trong container mà chúng ta setup.
Điều này sẽ cho phép ta có thể tạo được các file bên trong image web và chúng cũng sẽ xuất hiện ở dưới hệ thống local.
Chúng ta sẽ chỉnh sửa Dockerfile như sau:

FROM ruby:alpine RUN apk add --update build-base postgresql-dev tzdata
RUN gem install rails -v '5.1.6'

Sau khi đã chỉnh sửa ta sẽ chạy lại lệnh

$ docker-compose build web

Nó sẽ build lại file image của ta với gem Rails bên trong, sau đó ta có thể chạy được lệnh rails new
Tiếp theo chúng ta cần thay đổi ile docker-compose.yml để thêm volumesworking directory

version: '3.6' services: web: build: . volumes: - ./:/app working_dir: /app

Sau khi đã chỉnh sửa như trên, ta có thể chạy docker compose với câu lệnh rails new. Chúng ta sẽ tạo ra một application với database là Progres, bỏ qua javascript và các config khác bằng cách chạy câu lệnh

$ docker-compose run web rails new --database=progresql -J --skip-coffee

Sau khi chạy câu lệnh này thành công, thì thư mục của ta đã có đầy đủ file, folder cần thiết cho một rails app đơn giản và nó cũng gen ra cả Gemfile, Gemfile.lock
Khi sử dụng deploy bằng cách truyền thống, Bundler sẽ install các gem vào trong hệ thống file local. Do đó khi chạy câu lệnh như rails server nó sẽ load gem một ở local. Tuy nhiên khi ta sẽ dụng docker, docker-compose, gem cần phải được install vào trong image thay vì ở một nơi riêng biệt. Khi ta chạy rails new, nó sẽ install gem và sinh ra các file ở bên trong một file tạm thời. Để sửa và thực hiện như ta mong muốn ta sẽ sủa Dockerfile như sau

FROM ruby:alpine RUN apk add --update build-base postgresql-dev tzdata
RUN gem install rails -v '5.1.6' WORKDIR /app
ADD Gemfile Gemfile.lock /app/
RUN bundle install

Chúng ta vừa sửa để chỉ thêm GemfileGemfile.lock vào thư mục /app, sau đó sẽ chạy bundle install. Lý do chúng ta không cho cả thư mục vào image bởi vì là môt khi một file trong app thay đổi, docker sẽ hiểu là image này đang bị cũ, cần phải chạy lại thay vì sử dụng cache. Gemfile này ít thay đổi nên ta có thể thêm vào để tăng tốc đội build vì docker sẽ sử dụng cache nếu như không có gem nào được thêm vào cũng như thay đổi. Ta sẽ chạy lại

docker-compose build web

Tiếp đến, ta sẽ thay đổi file docker-compose.yml như sau

version: '3.6' services: web: build: . volumes: - ./:/app working_dir: /app command: puma ports: - 3000:3000

Tại đây chúng ta sẽ add câu lệnh để start server puma trên cổng 3000. Ta sẽ chạy câu lệnh

docker-compose up web

Sau đó có thể vào đường dẫn http://localhost:3000 để xem kết quả.

2. Tạo model và migration

Tiếp theo chúng ta sẽ tạo một model đơn giản và migrate database
Tạo một model Post bằng cách chạy lệnh

$ docker-compose run --rm web rails g model Post content:text

Nó sẽ tạo một model Post và migrate bên trong container của chúng ta. Bởi vì ta đã định nghĩa volumes bên trong file docker-compose.yml , nó cũng sẽ nằm ở dưới hệ thống local.
Tiếp theo nếu ta chạy

$ docker-compose run --rm web rails db:migrate
rails aborted!
PG::ConnectionBad: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

Nó sẽ hiển thị lỗi chúng ta cần start progres database cho rails app để có thể kết nối đến được. Để làm ta sẽ thêm một image progres vào trong docker-compose.yml

version: '3.6' services: web: build: . volumes: - ./:/app working_dir: /app command: puma ports: - 3000:3000 depends_on: - db environment: DATABASE_URL: postgres://postgres@db db: image: postgres:10.3-alpine

Chúng ta vừa add thêm một service khác là db và sử dụng image progres. Chúng ta cũng thêm 2 phần nữa vào phần web đó là depends_on để chắc chắn rằng image progres đã được start và biến enviroment để cho rails app biết kết nối với nó như thế nào. Chúng ta cũng cần phải thay đổi file config/database.yml như sau

default: &default adapter: postgresql encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> url: <%= ENV['DATABASE_URL'] %> development: database: app_development test: database: app_test

Từ đây, ta có thể tạo database và run migrations

$ docker-compose run --rm web rails db:create db:migrate

Lệnh --rm để loại bỏ container được sử dụng để chạy câu lệnh này, để tiết kiệm được bộ nhớ dưới local.
Tiếp theo, ta sẽ tạo một dữ liệu với bảng posts vừa tạo bằng cách chạy

$ docker-compose run --rm web rails runner 'Post.create(content: "this is content of post")'

Thay đổi file config/routes.rb

Rails.application.routes.draw do root to: 'posts#index'
end

Tạo file controller

class PostsController < ApplicationController def index post = Post.order('RANDOM()').first render html: post.content end
end

Chúng ta sẽ chạy lại lệnh

docker-compose up web

Sau đó đến localhost:3000 để xem kết quả. Bài post ta vừa tạo sẽ xuất hiện trên màn hình

3. Deploy app lên Heroku

Bước cuối cùng chúng ta sẽ deploy app vừa tạo lên heroku. Ta sẽ thay đổi Dockerfile như sau

FROM ruby:alpine RUN apk add --update build-base postgresql-dev tzdata
RUN gem install rails -v '5.1.6' WORKDIR /app
ADD Gemfile Gemfile.lock /app/
RUN bundle install ADD . .
CMD ["puma"]

Nó sẽ add những file local của ta(tất cả các file trong rails app) vào trong image và sau đó set câu lệnh default là puma. Do đó, khi ta run docker run nó sẽ tự động sử dụng puma.
Ta sẽ deploy Docker image lên Heroy bằng cách

$ git init // để tạo một repos trống

Sau đó chạy

$ heroku create

Ta cần phải login vào heroku và đẩy Docker image lên đó

$ heroku container:login
$ heroku container:push web
$ heroku container:release web

Chúng ta cần phải set up cho database progres bằng tay bằng cách chạy lệnh

$ heroku addons:create heroku-postgresql:hobby-dev

Tiếp đến ta cần phải thêm một vài biến môi trường cho nó

$ heroku config:set RAILS_ENV=production SECRET_KEY_BASE=supersecret RAILS_LOG_TO_STDOUT=true

Nó sẽ boot app của ta lên product (được định nghĩa trong config/environments/production.rb) và logs vào STDOUT cho phép ta nhìn được log khi sử dụng câu lệnh heroku logs
Tiếp đến ta sẽ migrate database trên heroku

$ heroku run rails db:migrate

Tạo dữ liệu mới của bảng posts trên heroku

$ heroku run rails runner 'Post.create(body: "This is content of post")'

Sau đó ta sẽ chạy và xem kết quả ?

$ heroku open

4. Kết luận

Như vậy ta đã vừa tìm hiểu xong cách để deploy một ứng dụng rails đơn giản sử dụng docker. Hi vọng bài viết giúp ích cho mọi người, nếu có gì góp ý hay thảo luận hãy để lại bình luận phía dưới. (See you)

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 397

- vừa được xem lúc

Phần 1: Giới thiệu về Kubernetes

Kubernetes là gì. Trang chủ: https://kubernetes.io/. Ai cần Kubernetes.

0 0 100

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 1- Lịch sử)

1. Vì sao nên sử dụng. . .

0 0 104

- vừa được xem lúc

Docker - những kiến thức cơ bản phần 1

Giới thiệu. Nếu bạn đang làm ở một công ty công nghệ thông tin, chắc rằng bạn đã được nghe nói về Docker.

0 0 78

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 2 - Dockerfile)

1. Mở đầu.

0 0 67

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 3: Docker-compose)

1. Mở đầu. . .

0 0 121