search
Đăng ký nhận khóa học miễn phí và bài viết hướng dẫn qua email
Cài đặt môi trường phát triển Ruby on Rails sử dụng Docker
Views : 646 by Kevin Nguyen in Ruby On Rails

Giới thiệu

Bài viết này trình bày cách triển khai một môi trường phát triển Ruby on Rails thống nhất trên 3 nền tảng hệ điều hành là Windows, Ubuntu và MacOS.

Thực chất môi trường Ubuntu và MacOS không gặp vấn đề gì khi lập trình phát triển Rails nhưng Windows lại không thân thiện cho lắm, ngoài ra nếu nhóm của bạn mỗi người dùng một hệ điều hành do sở thích hay do đang dùng máy Mac thì việc xây dựng nền tảng chung là cần thiết.

Cho đến hiện nay thì việc cài đặt môi trường phát triển Rails trên Windows vẫn mang lại những lo lắng về việc phát sinh lỗi không mong muốn, nghĩa là những lỗi không hề xuất hiện trên Ubuntu hay MacOS và thực ra không đáng gọi là lỗi.

Nếu bạn sử dụng Windows thì có các sự lựa chọn sau:

  • Cài đặt Rails thông qua chương trình RailsInstaller tại Website: http://railsinstaller.org
  • Cài đặt thông qua "Windows Subsystem for Linux" tại Control Panel
  • Sử dụng máy ảo Ubuntu chạy bằng VirtualBox hay VMWare
  • Sử dụng Docker chạy trên Hyper-V của Windows

Là người từng cài đặt và sử dụng tất cả các giải pháp, tôi sẽ đưa ra phân tích để có sự lựa chọn hợp lý nhất.

Đối với việc sử dụng RailsInstaller, đây là một chương trình cài đặt Windows tiêu chuẩn với phần mở rộng là .exe, người dùng chỉ việc Next và Next. Nó tạo cảm giác dễ dàng sử dụng nhưng thực chất lại ẩn chứa sóng gió bên trong, ưu điểm chỉ là dễ cài đặt, nhược điểm thì hơi nhiều.

Đầu tiên là việc bạn sẽ không bao giờ có một phiên bản Ruby hay Rails mới nhất, nó luôn đi chậm 2 đến 3 bước về phiên bản. Tiếp theo là các lỗi thường xuyên xuất hiện khi biên dịch các gói native, tức là gói cần download mã nguồn và biên dịch trực tiếp trên Windows, nhiều khi việc cài đặt một gem thành công là cả một phép màu.

Ngoài ra thì Rails không chạy một mình, nó cần làm việc với MySQL/PosgreSQL/Redis và các tác vụ nền cron job, mấy cái này sẽ chạy quờ quạng trên Windows. Tôi nghĩ bạn không nên mất thời gian nhiều cho giải pháp này, trên các cộng đồng mạng khi có câu hỏi nào đó về lỗi trên Windows thì lời khuyên là nên chuyển sang Ubuntu.

Đối với cái gọi là "Windows Subsystem for Linux", đây là một bản phân phối Ubuntu 14 được MS đưa vào dưới chế độ dành cho nhà phát triển, bạn có thể vào Control Panel > "Turn Windows Features on or off" > "Windows Subsystem for Linux".

Cho đến thời điểm 2017 nó vẫn chưa thoát kiếp beta và nó là một nỗ lực để thu gom các nhà phát triển Linux về Windows. Suy cho cùng thì mục đích là tốt nhưng hiện tại thì nó chưa ổn, tôi đã bật lên, cài đặt Ruby sau đó là Rails và cuối cùng lên google để tìm cụm từ "How to uninstall Windows Subsystem for Linux".

Sau này có dịp tôi sẽ kiểm tra lại và sử dụng nếu nó thực sự tốt.

Đối với máy ảo Ubuntu chạy bằng VirtualBox hay VMWare, đây là giải pháp khá tốt và chúng ta có một môi trường Linux thực sự để phát triển, nhược điểm là nó nặng và chạy chậm do hoàn toàn ảo hóa, nếu này bạn cấu hình cao thì đây là lựa chọn không tồi.

Nếu chọn giải pháp này chúng ta sẽ download bản iso của Ubuntu và cài đặt vào VM, sau đó cài Ruby/Rails như trên Ubuntu thật, và cuối cùng là ssh từ Windows vào máy ảo, sử dụng Ruby như một Remote Interpreter bình thường.

Cuối cùng chỉ còn lại Docker, đây là công nghệ mới sinh ra với ý tưởng phục vụ cho kiến trúc MicroService, mỗi container sẽ chạy một dịch vụ riêng biệt, tất cả share chung Kernel với hệ điều hành chủ nếu nó là Linux.

Điều này làm cho nó có hiệu năng tốt hơn rất nhiều so với ảo hóa truyền thống nhưng vẫn đảm bảo tính cách ly với Host OS.

Docker chạy tốt nhất trên server linux như Ubuntu hay Redhat/Centos vì nó tuy ảo mà thật.

Trên Windows thì tất nhiên phải ảo hóa, Docker sẽ chạy trên nền ảo hóa Hyper-V của Windows, cá nhân tôi thấy chạy nhẹ hơn các VM khác, ngoài ra còn đảm bảo ssh được như server thật và share thư mục source code tại local với các IDE để lập trình. Quan trọng hơn là thống nhất môi trường phát triển cho cả team dù họ chạy HĐH khác nhau.

Cài đặt Docker trên Windows

Yêu cầu để sử dụng được Docker trên Windows:

  • Phiên bản Windows 64-bit Professional hoặc Enterprise
  • RAM từ 4GB trở lên
  • CPU hỗ trợ ảo hóa, có thể xem trong BIOS

Bước 1: Tải về bản Stable Community Edition tại

https://docs.docker.com/docker-for-windows/install

Bước 2: Bật tính năng ảo hóa Hyper-V trong Control Panel > Turn Windows Features on or off > Hyper-V

Bước 3: Cài đặt bình thường và chạy Docker, sau đó vào mục Settings của nó chọn lựa chọn "Shared Drives", chọn ổ cứng nào mà bạn dự định sẽ chứa thư mục code, hoặc đánh dấu tất cả.

Mỗi khi khởi động lại Windows chúng ta cần chờ cho Docker khởi động trước khi sử dụng.

Cài đặt Docker trên Ubuntu

Yêu cầu vẫn là bản Ubuntu 64-bit và có trên 4GB RAM

Gỡ phiên bản cũ nếu có

sudo apt-get remove docker docker-engine
sudo apt-get purge docker-ce
sudo rm -rf /var/lib/docker

Cài đặt dùng file .deb mới nhất tại, bản mới nhất thường ở dưới cùng hoặc căn cứ vào ngày phát hành :

https://download.docker.com/linux/ubuntu/dists/trusty/pool/stable/amd64

Chú ý lựa chọn tên mã cho phiên bản Ubuntu của bạn, đối với Ubuntu 17 là "trusty", sử dụng kiến trúc amd64.

Đối với các bản Ubuntu khác thì quay lui đường dẫn về : https://download.docker.com/linux/ubuntu/dists sau đó chọn tên tương ứng.

Lệnh xem tên mã của Ubuntu hiện đang sử dụng

. /etc/os-release

Lệnh bao gồm dấu chấm ở đầu, sau đó đến dấu cách.

Tải về file cài đặt

wget https://download.docker.com/linux/ubuntu/dists/trusty/pool/stable/amd64/docker-ce_17.06.2~ce-0~ubuntu_amd64.deb
sudo dpkg -i docker-ce_17.06.2~ce-0~ubuntu_amd64.deb

Chạy kiểm tra sau khi cài đặt

sudo docker run hello-world

Trình quản lý Docker là non-root user, do vậy cần tạo docker group.

sudo groupadd docker

Thêm tên user tài khoản của bạn vào docker group.

sudo usermod -aG docker $USER

Cho phép Docker chạy khi reboot

sudo systemctl enable docker

Cài đặt Docker trên MacOS

Cài đặt Docker trên MacOS rất đơn giản, truy cập vào:

https://docs.docker.com/docker-for-mac/install

Tải về phiên bản stable và sau đó cài đặt file dmg bình thường, kéo icon của Docker vào Applications và khởi động chương trình.

Đã xong quá trình cài đặt Docker trên 3 hệ điều hành, các bước tiếp theo sẽ trình bày cách xây dựng môi trường phát triển Ruby on Rails dựa trên Docker.

Cài đặt môi trường phát triển Rails

Chúng ta sẽ tải về image được cài đặt và tối ưu hóa cho quá trình phát triển Rails.

Phiên bản Ruby được hỗ trợ bắt đầu từ 2.4.0, để xem các phiên hiện có bạn vào website:

https://hub.docker.com/r/enziin/ruby/tags

Trước khi tải về hãy chắc chắn Docker đang chạy, trên Ubuntu/Mac chúng ta sử dụng Terminal, trên Windows chúng ta sẽ sử dụng "Windows PowerShell" thay cho CMD thông dụng, khởi động và thực thi lệnh

docker pull enziin/ruby:2.4.2

Chú ý: Nếu gặp lỗi Permission bạn cần reboot.

Lệnh này sẽ tải về image bao gồm:

  • Ubuntu 17.04
  • Ruby 2.4.2 quản lý với RVM
  • MySQL
  • SSH server
  • Redis server
  • Apache Webserver

Chạy container trên Windows

Tạo thư mục C:\developer trước khi chạy lệnh.

docker run -it -p 80:3000 -p 443:443 -p 22:22 -p 3306:3306 --name server-rails -v C:/developer/:/home/developer/ enziin/ruby:2.4.2 /bin/bash

(Trong video hướng dẫn thì dùng cổng 80:80 và 3000:3000, tuy nhiên chúng ta dùng như lệnh trên để cho phép cấu hình domain tùy biến)

Lệnh trên có tác dụng như sau:

  • Tạo một container từ image enziin/ruby:2.4.2 với tên là server-rails
  • Binding các cổng 443/22/3306 của cả bên Windows và server-rails
  • Binding cổng 80 bên Windows với cổng 3000 bên server-rails
  • Chia sẻ và ánh xạ thư mục C:\developer thành /home/developer/

Chạy Container trên Ubuntu

Tạo thư mục /home/kevin/developer trước khi chạy lệnh.

mkdir -p /home/kevin/developer
docker run -it -p 80:3000 -p 443:443 -p 22:22 -p 3306:3306 --name server-rails -v /home/kevin/developer/:/home/developer/ enziin/ruby:2.4.2 /bin/bash

(Trong video hướng dẫn thì dùng cổng 80:80 và 3000:3000, tuy nhiên chúng ta dùng như lệnh trên để cho phép cấu hình domain tùy biến)

Lệnh trên có tác dụng như sau:

  • Tạo một container từ image enziin/ruby:2.4.2 với tên là server-rails
  • Binding các cổng 443/22/3306 của cả bên Ubuntu và server-rails
  • Binding cổng 80 bên Ubuntu với cổng 3000 bên server-rails
  • Chia sẻ và ánh xạ thư mục /home/developer/ của cả hai bên.

Chạy container trên MacOS

Tạo thư mục /Users/kevin/developer trước khi chạy lệnh trên máy thật

cd
mkdir -p /Users/kevin/developer
docker run -it -p 80:3000 -p 443:443 -p 22:22 -p 3306:3306 --name server-rails -v /Users/kevin/developer/:/home/developer/ enziin/ruby:2.4.2 /bin/bash

(Trong video hướng dẫn thì dùng cổng 80:80 và 3000:3000, tuy nhiên chúng ta dùng như lệnh trên để cho phép cấu hình domain tùy biến)

Lệnh trên có tác dụng như sau:

  • Tạo một container từ enziin/ruby:2.4.2 với tên là server-rails
  • Binding các cổng 443/22/3306 của cả bên MacOS và server-rails
  • Binding cổng 80 bên MacOS với cổng 3000 bên server-rails
  • Chia sẻ và ánh xạ thư mục /Users/kevin/developer thành thư mục /home/developer/

Các bạn có thể thấy cổng 80/443 dành cho http/https, cổng 22 dành cho SSH và 3306 dành cho kết nối cơ sở dữ liệu.

Lệnh "docker run" sẽ tạo một container mới từ image tải về, đây là lệnh chạy một lần duy nhất, vì mỗi lần chạy sẽ sinh ra một bản sao mới.

Kết quả của lệnh này sẽ trả về một cửa sổ Terminal rất quen thuộc để chúng ta thao tác.

Thông tin các tài khoản của container

Đến đây chúng ta đã làm gì?

Chúng ta đã cài đặt Docker, tải về một image dựa trên kernel Ubuntu 17, đóng gói các dịch vụ cần thiết để chạy ứng dụng Rails thống nhất trên cả 3 hệ điều hành.

Image mà chúng ta vừa cài đặt cũng chỉ là một hệ điều hành Ubuntu thông thường, từ hệ điều hành chủ hoàn toàn có thể ssh đến và quản lý với các tài khoản dưới đây.

  • Một user bình thường với username/password là : developer / developer
  • Tài khoản quản trị MySQL là : root / developeradmin_db / developer
  • Kết nối SSH cổng chuẩn 22 bằng : developer / developer

Cài đặt Rails trong Docker

Sở dĩ trong image tải về không cài đặt Rails sẵn mà để cài đặt sau vì phải đảm bảo sự kết hợp linh hoạt giữa các phiên bản Ruby với Rails, dù sao thì Rails và các gem đi kèm cũng không quá nặng.

Chú ý:

  • Ruby 2.4.x sử dụng với Rails 5
  • Ruby 2.3.x sử dụng với Rails 4

Đầu tiên chúng ta cho phép user có tên "developer" quyền được sử dụng rvm

chown -R developer:developer /usr/local/rvm
chown -R developer:developer /home/developer
chmod -R 777 /home/developer

Lệnh có thể mất hơn 10s để thực hiện do số lượng file trong thư mục rvm lớn.

Sau đó cài đặt Rails bản mới nhất

gem install rails

Để cài một phiên bản chỉ định sẵn

gem install rails -v '5.1.4'

Tại cửa sổ Terminal với quyền root và tại thư mục gốc chúng ta chạy kịch bản khởi động

./start.sh

Lệnh này sẽ khởi động các dịch vụ cần thiết như ssh, apache, mysql, redis ...

Nếu có bất kỳ dịch vụ nào fails thì đơn giản chúng ta sẽ chạy lại kịch bản start.sh

Phần quan trọng tiếp theo: chúng ta để nguyên cửa sổ Terminal root đang chạy, mở một cửa sổ Terminal mới trên Ubuntu/MacOS hoặc Putty trên Windows và kết nối ssh đến container đã tạo.

ssh developer@localhost

Tạo ứng dụng ví dụ có tên blog để thử, sử dụng mysql

rails new blog -d mysql
cd blog

Thay đổi thông tin cấu hình database cho ứng dụng tại /blog/config/database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  wait_timeout: 300
  username: admin_db
  password: developer
development:
  <<: *default
  database: blog_db

Sau đó tạo một model đơn giản

rails generate scaffold User name:string email:string

Tạo database

rails db:create
rails db:migrate

Chạy ứng dụng

rails server

Chúng ta thêm vào lệnh phân giải domain:

Trên Windows tại tập tin : C:\Windows\System32\drivers\etc\hosts

Trên Ubuntu và MacOS tại : /etc/hosts

127.0.0.1    www.blog.com
127.0.0.1    blog.com

Chúng ta có thể tùy biến blog.com thành bất cứ tên miền nào của bạn.

Xem kết quả

http://www.blog.com

Hoặc:

http://www.blog.com/users

Cài đặt DBeaver Community Edition và kết nối với container bằng tài khoản:

  • Localhost
  • Port : 3306
  • Database: blog_db
  • Username: admin_db
  • Password: developer

Kiểm tra rails dbconsolerails consle như video hướng dẫn.

Một phiên làm việc điển hình

Như đã nói ở trên, mỗi lần chạy lệnh "docker run" sẽ tạo ra một container mới (trừ khi bạn muốn thế)

Do vậy chúng ta sẽ start và stop container mỗi phiên làm việc bình thường.

Lệnh khởi động container thông qua tên

docker start -a -i server-rails

Sau đó chạy kịch bản

./start.sh

Để nguyên cửa sổ root, chúng ta mở cửa sổ ssh với tài khoản developer, đây chính là cửa sổ sẽ tương tác với ứng dụng Rails.

Hết phiên làm việc, chúng ta logout trong cửa sổ ssh và gõ exit tại cửa sổ root

exit

Docker và các IDE

Docker container chúng ta tạo ở trên làm việc tốt với các trình editor thông dụng hiện nay như Bracket, Visual Studio Code, Rubymine ...

Bạn chỉ cần mở thư mục share là chúng ta sẽ làm việc bình thường, code của cả hai phía sẽ là một, cho phép soạn thảo realtime ở local và chạy trên container docker.

Đối với trường hợp của Rubymine còn cho phép kết nối Ruby trong container và phân tích các gem để sử dụng tự nhiên như phía local.

Thiết lập kết nối trong Rubymine > Settings > Ruby SDK and Gems

Chọn remote và nhập vào thông tin ssh như localhost, cổng 22, tài khoản developer/developer

Chọn đường dẫn của gem là : /usr/local/rvm/gems/ruby-2.4.2

Mọi việc còn lại sẽ do Rubymine đảm nhận.

Các lệnh thao tác thường dùng trong Docker

Phần này dành cho ai thích vọc hoặc thay đổi theo yêu cầu

Liệt kê các image có sẵn

docker images

Liệt kê các container có sẵn

docker ps -aG

Liệt kê các container đang chạy

docker ps

Tải về một image

Vào trang https://hub.docker.com/explore

docker pull {author_name}/{image_name}

Ví dụ :

docker pull ubuntu:17.10

Xóa 1 image

Ta chỉ xóa được image khi KHÔNG CÒN container nào được tạo ra từ image đó nữa.

docker rmi image_id

Tạo mới một container từ image

docker run -i -t --name my-os ubuntu:17.10 /bin/bash

Chạy lại một container đã stop, dùng lệnh:

docker start -a -i container_id

Xóa 1 container, chỉ xóa được container khi nó đã bị stop.

docker rm container_id

Để xóa TẤT CẢ các container đã stop:

docker rm `docker ps --no-trunc -aq`

Mã nguồn DockerFile

Dưới đây liệt kê mã nguồn của dockerfile dành cho image có tên "enziin/ruby" mà chúng ta đã tải về.

Nếu bạn hiểu mình đang và sẽ làm gì bạn có thể sửa theo ý muốn của mình các thông tin như:

  • Phiên bản Ruby sẽ cài đặt
  • Tên và password của các loại tài khoản đang có như developer, admin_db, root mysql...
  • Tên các thư mục liên quan /home/developer...

Tạo file tên là "dockerfile" không có phần mở rộng tại một thư mục riêng và paste mã nguồn

FROM ubuntu:17.04

MAINTAINER Enziin System Inc.

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y locales locales-all
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8

RUN apt-get update && apt-get install --assume-yes apt-utils && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN apt-get update && apt-get install -y software-properties-common && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN apt-get update && apt-get install -y sudo nano gnupg2 vim tzdata dmsetup build-essential \
 git git-core subversion nodejs libmagickwand-dev imagemagick libpq-dev curl \
 libcurl4-openssl-dev libapr1-dev libaprutil1-dev apache2 && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN update-rc.d apache2 defaults

RUN mkdir -p /home/developer

RUN apt-get update && apt-get install -y rubygems && gem update --system && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 && curl -sSL https://get.rvm.io | bash -s stable

RUN echo "source /etc/profile.d/rvm.sh" >> ~/.bashrc

RUN /bin/bash -l -c "source /etc/profile.d/rvm.sh" && /bin/bash -l -c "rvm install 2.4.2" \
&& /bin/bash -l -c "rvm use 2.4.2"

#Install mysql

RUN apt-get update && apt-get install -y libmysqlclient-dev && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN echo "mysql-server-5.5 mysql-server/root_password password developer" | debconf-set-selections
RUN echo "mysql-server-5.5 mysql-server/root_password_again password developer" | debconf-set-selections

RUN apt-get update && apt-get install -y mysql-server && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN update-rc.d mysql defaults

RUN echo "[mysqld]" >> /etc/mysql/my.cnf && echo "bind-address        = 0.0.0.0" >> /etc/mysql/my.cnf

RUN apt-get update && apt-get install -y redis-server && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN chown -R mysql:mysql /var/lib/mysql && usermod -d /var/lib/mysql/ mysql

RUN apt-get update -y \
  && apt-get -y install \
    openssh-server \
  && echo "PidFile ${RUN_DIR}/sshd.pid" >> /etc/ssh/sshd_config \
  && sed -i 's|session    required     pam_loginuid.so|session    optional     pam_loginuid.so|g' /etc/pam.d/sshd \
  && mkdir -p /var/run/sshd \
  && rm -rf /var/lib/apt/lists/*

EXPOSE 22
EXPOSE 80
EXPOSE 443
EXPOSE 3000
EXPOSE 3306

Sau đó build image tùy biến

docker build -t your-company/name-image:version .

Ví dụ

docker build -t enziin/ruby:2.4.2 .

(Lệnh bao gồm cả dấu chấm cuối cùng)

Sau khi build image chúng ta có thể export thành file nén để chuyển sang máy khác

docker save -o /directory/your-image.tar your-company/name-image:version

Ví dụ

docker save -o /home/kevin/enziin.tar enziin/ruby:2.4.2

Sau đó có thể copy và sử dụng file .tar

docker load -i enziin.tar

Hoặc cũng có thể đẩy lên kho chứa chung của cộng đồng Docker

Đăng ký tài khoản tại : https://hub.docker.com

Và từ cửa sổ Terminal

docker login

Nhập vào username và password, sau đó đẩy image lên

docker push your-company/name-image:xxx.xxx

Ví dụ

docker push enziin/ruby:2.4.2

Chúc thành công!

Next : Cài đặt môi trường phát triển Ruby on Rails trên MacOS