[Docker Compose] Build ứng dụng Rails, PostgreSQL một cách đơn giản nhất

Lời mở đầu

Mình là một lập trình viên và mình chưa từng viết một dòng code ruby nào, chưa có build ứng dụng ruby on rails bao giờ, và rồi một ngày đẹp trời mình nhận được một nhiệm vụ dường như rất đơn giản đó là chạy một ứng dụng ruby on rails kết nối với hệ quản trị cơ sở dữ liệu PostgreSQL trên môi trường máy local của mình. Có thể với những bạn đang là dev ruby thì việc này sẽ hoàn thành chỉ trong một nốt nhạc, thế nhưng với mình lại khác, một loạt câu hỏi mình đã đặt ra:

  • Cần cài đặt những gì?
  • Chạy những precommands nào?
  • Start server như thế nào?
  • Mình còn chưa dùng thằng PostgreSQL trên môi trường local bao giờ thì làm sao nhỉ :-?

Vậy mục đích bài viết này của mình là để chỉ ra cho bạn từ một lập trình viên không biết gì về ruby có thể tạo môi trường phát triển cho ứng dụng ruby rails ngay trên máy tính của bạn một cách đơn giản.

Giải pháp

Mình hướng tới là build ứng dụng chứ không phải phát triển ứng dụng rails do đó giải pháp mình chọn đó là sử dụng docker một cách đơn giản để tạo môi trường develop cũng như testing. Một số khái niệm cần biết về docker bạn có thể tham khảo bài viết trước của mình Docker với lập trình viên web

Yêu cầu

  • Cài đặt dockerdocker-compose trên máy của bạn
  • Bài hướng dẫn của mình được thực hiện trên hệ điều hành ubuntu 16.04

Thực hiện

Đưa thư mục làm việc về rails project

  • Sau khi đã cài đặt xong docker và docker-compose trên máy thì việc đầu tiên mình cần thực hiện đó là download project rails về máy của mình. Bạn có thể tham khảo một sample app có sẵn trên git-hub.

Định nghĩa Dockerfile

  • Đi tới đường dẫn thư mục project đã clone tạo Dockerfile với nội dung như sau

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

Chú thích Dockerfile: Phiên bản ruby:2.3.1 thì bạn có thể tùy chỉnh phiên bản sao cho phù hợp với project mà bạn đang muốn build Update apt packages và cài đặt các một số additional requirements cho Rails Để code project của mình có thể chạy được bên trong container mình sẽ tạo sẵn thư mục myapp để copy code bên ngoài máy host của mình vào trong container. Chọn đường dẫn làm việc hiện tại sẽ là trong myapp Copy Gemfile và Gemfile.lock Bundle install để cài đặt các gói dependency cần thiết cho project Copy toàn bộ source code vào /myapp

Pull Postgres image

Nếu chỉ dừng lại ở đây thì ứng dụng của mình sẽ chỉ chạy nếu như nó không có sử dụng kết nối tới tớ cơ sở dữ liệu. Tuy nhiên ứng dụng như mình đề cập có sử dụng kết nối với database là PostgreSQL do đó mình cần một image PostgreSQL và sẽ sử dụng Docker-compose kết nối mọi thứ với nhau.

  • Pull Postgre image từ trên cộng đồng docker-hub, vẫn lựa chọn phiên bản phù hợp sau dấu :. Ví dụ mình sẽ sử dụng phiên bản postgreSQL 9.4
    $ docker pull postgres:9.4
    

Định nghĩa file docker-compose.yml

  • Tại thư mục làm việc trong ứng dụng của bạn, cùng với Dockerfile tạo file docker-compose.yml với nội dung như sau ( Ở đây mình vẫn sử dụng docker-compose version 2, hiện tại đã có version 3 nếu như bạn muốn tìm hiểu thêm)
    version: '2'
    services:
      db:
        image: postgres:9.4
        environment:
          POSTGRES_USER: pguser
          POSTGRES_PASSWORD: password
          POSTGRES_DB: myapp
      web:
        build: .
        command: bundle exec rails s -p 3000 -b '0.0.0.0'
        volumes:
          - .:/myapp
        ports:
          - "3000:3000"
        links:
          - db
    

Một lợi ích nữa của việc sử dụng docker-compose đó là mình sẽ không cần nhớ câu lệnh để start, stop server ứng dụng rails là gì, mình chỉ cần biết tới nó một lần và định nghĩa ngay trong file docker-compose.yml Bạn sẽ đặt ra một câu hỏi đó là tại sao trong Dockerfile đã add source code vào trong image rồi mà trong docker-compose.yml cần khai báo mount thư mục source code ở máy host của mình vào nữa?. Lý do ở đây đó chính là nếu mình chạy docker buil . thì nó sẽ được thực hiện tại thời gian build time còn docker-compose sẽ làm việc trong suốt quá trình run time để đảm bảo rằng bạn có thay đổi code trên máy host thì sẽ không cần khởi động lại container, mà code mới và kết quả nó trả về sẽ luôn được cập nhật. Các khai báo bên trong docker-compose file của mình đều rất cơ bản và mình đã giới thiệu từ những bài post trước về docker của mình nên mình sẽ không nói lại ở đây nữa.

Như vậy mình đã có một bản thiết kế đầy đủ cho images gồm những gì, container sau khi được tạo ra sẽ như thế nào.

Config ứng dụng để kết nối database

Trong file config/database.yml

default: &default
  adapter: postgres
  encoding: utf8
  pool: 5
  username: pguser
  password: password
  host: db

development:
  <<: *default
  database: myapp

username và password của db thì mình sẽ follow theo khởi tạo trong docker-compose file.

Kiểm tra lại trước khi khởi chạy

  • Mình có thể gặp phải lỗi ngay ở lần chạy ứng dụng đầu tiên có thể vì lí do xung đột cổng. Giả sử ở đây mình đang expose ra web cổng 3000 do đó để access thì bạn cần kiểm tra rằng trên máy của bạn cổng 3000 có đang bị thằng nào sử dụng không, nếu có thì mình có thể sửa lại chút trong docker-compose.yml là sẽ expose ra một cổng khác. Để kiểm tra những cổng nào đang được sử dụng thì có thể dùng lệnh sau: $ netstat -ntlp

Khởi chạy

Chạy docker-compose

$ docker-compose up

Tạo dữ liệu ban đầu

Do database đã được khởi tạo khi mình stat docker-compose do đó mình chỉ cần migrate data. $ docker-compose exec web bundle exec rake db:migrate Câu lệnh trên sẽ được thực hiện trong container có chứa service web. Nếu project của bạn có tạo seef file cho database thì chạy lệnh $ docker-compose exec web bundle exec rake db:seed

Đó là các bước đủ để mình build một ứng dụng rails, giờ việc còn lại là kiểm tra kết quả tại địa chỉ localhost:3000

Start/Stop container

Bạn có thể start/stop service tùy vào mục đích sử dụng Mỗi lần như vậy chỉ cần vào đường dẫn trong mục project (cùng đường dẫn với docker-compose.yml) ` #stop $ docker-compose stop

#start docker-compose start `

Tham khảo

Kết luận

  • Qua bài viết mong là đã giúp ích được cho bạn trong việc buil một ứng dụng rails cũng như tìm hiểu về Docker.
  • Cảm ơn bạn đã dành thời gian đọc bài chia sẻ của mình!