Xây dựng môi trường cho ứng dụng Ruby on Rails với Docker, Docker-Compose
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 Nếu bạn mới làm quen hoặc chưa biết về docker bạn có thể ghé qua đây Tạo file docker: touch Dockerfile Nội dung hoàn ...
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
Nếu bạn mới làm quen hoặc chưa biết về docker bạn có thể ghé qua đây
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
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.
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