Xây dựng môi trường cho ứng dụng Ruby on Rails với Docker, Docker-Compose
This post hasn't been updated for 7 years
Cài đặt:
Tất nhiên để dùng Docker và Docker-Compose trước tiên chúng ta phải cài đặt chúng rồi. Thông tin cách thức chi tiết bạn có thể xem tại đây cho Docker , Docker-compose
Giới thiệu:
Nếu bạn mới làm quen hoặc chưa biết về docker bạn có thể ghé qua đây
1. Init:
Tạo file docker:
touch Dockerfile Nội dung hoàn chỉnh của file (mình sẽ chỉ rõ ý nghĩa của từng line phía dưới):
FROM ruby
RUN apt-get update -qq && apt-get install -y build-essential nodejs
RUN mkdir /rails-app
WORKDIR /rails-app
ADD Gemfile /rails-app/Gemfile
ADD Gemfile.lock /rails-app/Gemfile.lock
RUN bundle install
ADD . /rails-app
FROM
để chỉ định image mà chúng ta sẽ sử dụng, tất nhiên bạn có thể bắt đầu từ image ubuntu và tự mình install những gì bạn cần nhưng thường thì tất cả những gì chúng ta cần đều đã có sẵng nên, cứ lười biến dùng lại là ok rồi.
Ở đây mình sử dụng image cho ruby là latest version bạn có thể quyết định version sử dụng image có version nào bằng cách
// thay
FROM ruby
// thành
FROM ruby:2.x.x
Vì mình chỉ chọn dùng image ruby only mà không dùng image bao gồm rails vì để có thể thỏa mái lựa chọn rails version vào ruby version nên trong Dockerfile
mình phải install nodejs qua line:
RUN apt-get update -qq && apt-get install -y build-essential nodejs
Tạo vài chỉ định thư mục làm việc của dự án trong docker container, với tên là rails-app
thực sự thì bạn cũng sẽ không cần quan tâm lắm đến tên này,
RUN mkdir /rails-app
WORKDIR /rails-app
add 2 file cơ bản để init cho 1 ứng dụng rails tử thư mục chức src của dự án vào container:
ADD Gemfile /rails-app/Gemfile
ADD Gemfile.lock /rails-app/Gemfile.lock
Mình mới chỉ ADD
2 file này mà không hề tạo như folder rails-app
nên chúng ta cần tạo 2 file này:
touch Gemfile Gemfile.lock Ở đây tại sao mình lại tạo 2 file này tại máy mà không dùng 1 line tương tự như :
RUN touch /rails-app/Gemfile /rails-app/Gemfile.lock
hoặc
RUN touch Gemfile Gemfile.lock
Nếu bạn tạo 2 file này trong container thì nó sẽ bị ẩn đi và thứ 2 là nó sẽ được tạo với quyền root dẫn đến khó khăn trong việc change 2 file này.
init rails
Giờ thì init rails nào:
./Gemfile
source 'https://rubygems.org'
gem 'rails', '5.0.0.1'
Làm việc với Gemfile có lẽ đã quá quen thuộc nên mình sẽ để đây và không nói gì thêm.
Bây h thì hoàng thành việc init cho rails với command:
rails new . --force --database=mysql --skip-bundle
Mình chỉ mới tạo file docker cho ruby và init cho rails vậy thì h chúng ta cần khởi tạo các container khác như mysql. Để giới thiệu 1 cách dài dòng hơn mình sẽ tạo container cho cả redis và sidekiq,
và nếu bạn cần dùng sidekiq với redis thì thêm vào Gemfile
:
gem 'sidekiq'
gem 'sinatra', require: false
Tạo file docker-compose.yml
Như đã nói, tất cả những image chúng ta cần đều đã được tạo sẵng rồi nên chỉ việc dùng lại thôi, nội dung docker-compose.yml
:
version: '2'
services:
db:
image: mysql
ports:
- "3307:3307"
environment:
MYSQL_ROOT_PASSWORD: 123123
MYSQL_USER: root
MYSQL_PASSWORD: 123123
MYSQL_DATABASE: 123123
redis:
image: redis
environment:
- REDIS_URL=redis://redis:6379
sidekiq:
build: .
volumes:
- .:/rails-app
links:
- db
- redis
command: bundle exec sidekiq
environment:
- REDIS_URL=redis://redis:6379
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/rails-app
ports:
- "3000:3000"
depends_on:
- db
stdin_open: true
tty: true
Để có thể debug thì bạn cần 2 line:
stdin_open: true
tty: true
Config cho database
config/database.yml
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password: 123123
host: db
development:
<<: *default
database: my_app
Bây h đề pull các image mà chúng ta xử dụng và hoàn thành việc init với command:
docker-compose build
2. Run
Run
docker-compose up
Tạo database:
docker-compose run web rails db:create
Ứng dụng của bạn đã sẵng sàng để phát triển.
3. TIP-Các command thường dùng
TIP Nếu bạn là người phát triển ứng dụng, bạn bên bundle ứng dụng ngay tại thư mục thực tế:
bundle install
và chạy các lệnh greanate ngay tại đây để không mắc các vấn đề về khả năng truy cập của file được tạo. ví dụ: tạo 1model User thì nên:
rails g model User name:string
thay vì:
docker-compose run web rails g model User name:string
Còn nếu bạn là chỉ muốn run ứng dụng mà không quan tâm việc greanate thêm 1 thành phần nào của nó thì bundle
là việc không cần thiết.
Việc sử dụng lâu dài đôi khi sẽ phát sinh lỗi khi đang chạy hay vì vấn đề nào đó mà bạn cần rebuild lại các container, để xóa nhanh tất cả các container hiện tại:
docker rm -f $(docker ps -a -q)
Khi bạn thực hiện việc rebuild thì thường sẽ bắt gặp lỗi không thể start rails server, đây là vì bạn thay đổi container và các file temp tạo với quyền root của container trước đó không cho phép bạn access. Bạn cần remove nó đi, cụ thể là 2 folder tmp
và log
sudo chmod -R 777 tmp log rm -rf tmp log
Để debug thì bạn có thể dùng lệnh
docker attach [container-name/container-id]
nếu console có log tương tự như
Started GET "/assets/home-fcec5b5a277ac7c20cc9f45a209a3bcd.js?body=1" for 10.0.2.2 at 2015-04-02 15:48:31 +0000
Cannot render console from 10.0.2.2! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
cùng với đó bạn cần thêm vào config:
config.web_console.whitelisted_ips = '10.0.2.2' Đẹp hơn thì bạn đên đặt cho nó 1 env để mọi người trong team có thể config lại theo ip từng người config.web_console.whitelisted_ips = ENV["CONSOLE_IP"]
Kiểm tra các images hiện tại:
docker images
Xem các container:
- Đang chạy
docker ps
- Tất cả;
docker ps -a
All Rights Reserved