Môi trường cho ứng dụng rails, mysql với docker compose

Bạc xỉu

TL;DR

Hướng dẫn sử dụng Docker Compose cài đặt môi trường phát triển ứng dụng sử dụng rails-mysql.

Thiết lập môi trường

Bạn cần cài đặt docker compose trước khi bắt đầu

Dockerfile

Ứng dụng của bạn sẽ chạy trong một docker container cùng với các dependencies, các thiết lập hệ thống sẽ được đặt trong Dockerfile.

Dockerfile

FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

Các lệnh trong Dockerfile sẽ được đặt trong một image, sau đó dùng để tạo một container với ruby, bundler và các dependencies khác. Bạn có thể tìm hiểu thêm tại hướng dẫn viết dockerfile

Gemfile

Để có thể generate một rails project mà không cần cài đặt ruby hay rails trên môi trường hiện tại, bạn cần tạo một GemfileGemfile.lock và sau đó đặt trong container để thực hiện lệnh rails new. (2 file này sẽ bị overwrite ngay sau đó)

Gemfile

source 'https://rubygems.org'
gem 'rails', '5.2.0'
touch Gemfile.lock

docker-compose

Cuối cùng, file docker-compose.yml sẽ tạo ra các service có trong ứng dụng (cụ thể ở trong trường hợp này là database, web app). Sử dụng các image có sẵn và khai báo các tham số (port, directory,...)

version: '3'
services:
  db:
    image: mysql:5.7
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_USER: root
      MYSQL_ROOT_PASSWORD: root
    ports:
      - '3316:3306'
    volumes:
      - ./db/mysql/volumes:/var/lib/mysql

  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3001:3000"
    depends_on:
      - db

Khởi tạo project

Tạo project rails-mysql

docker-compose run web rails new . --force --no-deps --database=mysql

Sau khi tạo image cho web service bằng Dockerfile, lệnh rails new sẽ được chạy và tạo project mới trên container.

Nếu chạy trên môi trường linux, container được chạy với quyền root → lệnh rails new sẽ tạo ra các file với owner là root. Bạn có thể thay đổi bằng lệnh sudo chown -R user:user

Build image

Sau khi khởi tạo project, Gemfile của bạn đã thay đổi, việc build lại docker image là cần thiết.

docker-compose build

Kết nối database

MySQL đang được chạy trong container db thay vì localhost như default settings của rails, thêm nữa username và password cũng đã được thay đổi trong file docker-composer. Do đó cần phải thay đổi cấu hình trong config/database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: root
  host: db

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

Khởi động ứng dụng

docker-compose up
docker-compose run web rake db:create

Notes

  • Nếu không có lỗi xảy ra thì khi bạn đã có thể truy cập vào ứng dụng tại địa chỉ localhost:3001
  • Khi muốn dừng ứng dụng:docker-compose down
  • Nếu sử dụng Ctrl+C, có thể bạn sẽ bị lỗi "web_1 | A server is already running. Check /myapp/tmp/pids/server.pid.". Khi đó, hãy xoá file tmp/pids/server.pid và khởi động lại bằng lệnh docker-compose up
  • Khi có thay đổi trong Gemfile hoặc docker-compose, bạn cần thay đổi docker image.
    • Một vài thay đổi chỉ cần sử dụng: docker-compose up --build
    • Một vài thay đổi yêu cầu build lại từ đầu để có thể đồng bộ với Gemfile.lock: docker-compose run web bundle install
  • Một vài command:
    • List các container: docker ps
    • Truy cập shell của web container: docker-compose exec -it web bash
    • Kết nối với container console: docker attach
    • Khởi động lại container web: docker-compose restart web

Source code

Như thường lệ, các bạn có thể tham khảo source code chỉ có dockerfile tại đây và sau khi đã init project tại đây.

Refs:

Tags: #technical #docker #rails #mysql