Thứ sáu, 27/12/2019 | 00:00 GMT+7

Lưu trữ một ứng dụng Ruby on Rails để phát triển với Docker Compose

Nếu bạn đang tích cực phát triển một ứng dụng, việc sử dụng Docker có thể đơn giản hóa quy trình làm việc và quy trình triển khai ứng dụng của bạn vào production . Làm việc với containers đang phát triển mang lại những lợi ích sau:

  • Các môi trường nhất quán, nghĩa là bạn có thể chọn ngôn ngữ và phụ thuộc bạn muốn cho dự án của bạn mà không cần lo lắng về xung đột hệ thống.
  • Các môi trường được tách biệt, giúp khắc phục sự cố và giới thiệu thành viên group mới dễ dàng hơn.
  • Môi trường có tính di động, cho phép bạn đóng gói và chia sẻ mã của bạn với người khác.

Hướng dẫn này sẽ chỉ cho bạn cách cài đặt môi trường phát triển cho ứng dụng Ruby on Rails bằng Docker. Bạn sẽ tạo nhiều containers - cho chính ứng dụng, database PostgreSQL , Redis và dịch vụ Sidekiq - với Docker Compose . Việc cài đặt sẽ thực hiện như sau:

  • Đồng bộ hóa mã ứng dụng trên server với mã trong containers để tạo điều kiện thay đổi trong quá trình phát triển.
  • Duy trì dữ liệu ứng dụng giữa các lần khởi động lại containers .
  • Cấu hình công nhân Sidekiq để xử lý công việc như mong đợi.

Ở cuối hướng dẫn này, bạn sẽ có một ứng dụng thông tin cá mập đang hoạt động chạy trên containers Docker:

Trang chủ ứng dụng Sidekiq

Yêu cầu

Để làm theo hướng dẫn này, bạn cần :

Bước 1 - Nhân bản Dự án và Thêm Phụ thuộc

Bước đầu tiên của ta sẽ là sao chép repository rails-sidekiq từ tài khoản GitHub của Cộng đồng DigitalOcean . Kho lưu trữ này bao gồm mã từ cài đặt được mô tả trong Cách thêm Sidekiq và Redis vào Ứng dụng Ruby on Rails , giải thích cách thêm Sidekiq vào dự án Rails 5 hiện có.

Sao chép repository vào một folder có tên là rails-docker :

  • git clone https://github.com/do-community/rails-sidekiq.git rails-docker

Điều hướng đến folder rails-docker :

  • cd rails-docker

Trong hướng dẫn này, ta sẽ sử dụng PostgreSQL làm database . Để làm việc với PostgreSQL thay vì SQLite 3, bạn cần thêm pg gem vào các phụ thuộc của dự án, được liệt kê trong Gemfile của nó. Mở file đó để chỉnh sửa bằng nano hoặc editor bạn quen dùng :

  • nano Gemfile

Thêm đá quý vào bất kỳ đâu trong các phụ thuộc dự án chính (ở trên các phụ thuộc phát triển):

~ / rails-docker / Gemfile
. . .  # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.1.0', require: false gem 'sidekiq', '~>6.0.0' gem 'pg', '~>1.1.3'  group :development, :test do . . . 

Ta cũng có thể comment về gem sqlite , vì ta sẽ không sử dụng nó nữa:

~ / rails-docker / Gemfile
. . .  # Use sqlite3 as the database for Active Record # gem 'sqlite3' . . . 

Cuối cùng, hãy comment về viên ngọc spring-watcher-listen đang được development :

~ / rails-docker / Gemfile
. . .  gem 'spring' # gem 'spring-watcher-listen', '~> 2.0.0' . . . 

Nếu ta không vô hiệu hóa gem này, ta sẽ thấy các thông báo lỗi liên tục khi truy cập console Rails. Các thông báo lỗi này xuất phát từ thực tế là gem này có Rails sử dụng listen để theo dõi các thay đổi trong quá trình phát triển, thay vì thăm dò hệ thống file để tìm các thay đổi. Vì gem này theo dõi folder root của dự án , bao gồm cả folder node_modules , nó sẽ đưa ra các thông báo lỗi về folder nào đang được theo dõi, làm lộn xộn console . Tuy nhiên, nếu bạn lo lắng về việc bảo tồn tài nguyên CPU, việc tắt gem này có thể không phù hợp với bạn. Trong trường hợp này, bạn nên nâng cấp ứng dụng Rails của bạn lên Rails 6.

Lưu file khi bạn hoàn tất chỉnh sửa.

Với repository dự án của bạn, viên ngọc pg đã được thêm vào Gem file và viên ngọc spring-watcher-listen listening đã comment , bạn đã sẵn sàng cấu hình ứng dụng của bạn để hoạt động với PostgreSQL.

Bước 2 - Cấu hình ứng dụng để hoạt động với PostgreSQL và Redis

Để làm việc với PostgreSQL và Redis trong quá trình phát triển, ta sẽ muốn thực hiện những việc sau:

  • Cấu hình ứng dụng để hoạt động với PostgreSQL làm bộ điều hợp mặc định.
  • Thêm file .env vào dự án với tên user và password database của ta và server Redis.
  • Tạo một tập lệnh init.sql để tạo một user sammy cho database .
  • Thêm trình khởi tạo cho Sidekiq để nó có thể hoạt động với dịch vụ redis chứa trong vùng của ta .
  • Thêm .env file và các file khác có liên quan đến dự án gitignoredockerignore file .
  • Tạo hạt giống database để ứng dụng của ta có một số bản ghi để ta làm việc khi ta khởi động nó.

Đầu tiên, hãy mở file cấu hình database của bạn, có tại config/database.yml :

  • nano config/database.yml

Hiện tại, file bao gồm các cài đặt default sau, được áp dụng trong trường hợp không có cài đặt khác:

~ / rails-docker / config / database.yml
default: &default   adapter: sqlite3   pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>   timeout: 5000 

Ta cần thay đổi những điều này để cho biết là ta sẽ sử dụng bộ điều hợp postgresql , vì ta sẽ tạo một dịch vụ PostgreSQL với Docker Compose để duy trì dữ liệu ứng dụng của ta .

Xóa mã đặt SQLite làm bộ điều hợp và thay thế nó bằng các cài đặt sau, điều này sẽ đặt bộ điều hợp thích hợp và các biến khác cần thiết để kết nối:

~ / rails-docker / config / database.yml
default: &default   adapter: postgresql   encoding: unicode   database: <%= ENV['DATABASE_NAME'] %>   username: <%= ENV['DATABASE_USER'] %>   password: <%= ENV['DATABASE_PASSWORD'] %>   port: <%= ENV['DATABASE_PORT'] || '5432' %>   host: <%= ENV['DATABASE_HOST'] %>   pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>   timeout: 5000 . . . 

Tiếp theo, ta sẽ sửa đổi cài đặt cho môi trường development , vì đây là môi trường ta đang sử dụng trong cài đặt này.

Xóa cấu hình database SQLite hiện có để phần đó trông giống như sau:

~ / rails-docker / config / database.yml
. . .  development:   <<: *default . . . 

Cuối cùng, xóa cả cài đặt database cho môi trường productiontest :

~ / rails-docker / config / database.yml
. . .  test:   <<: *default  production:   <<: *default . . .  

Những sửa đổi này đối với cài đặt database mặc định của ta sẽ cho phép ta đặt động thông tin database của bạn bằng cách sử dụng các biến môi trường được xác định trong file .env , sẽ không được commit kiểm soát version .

Lưu file khi bạn hoàn tất chỉnh sửa.

Lưu ý nếu bạn đang tạo một dự án Rails từ đầu, bạn có thể đặt bộ điều hợp bằng lệnh rails new , như được mô tả trong Bước 3 của Cách sử dụng PostgreSQL với Ứng dụng Ruby on Rails của bạn trên Ubuntu 18.04 . Điều này sẽ đặt bộ điều hợp của bạn trong config/database.yml và tự động thêm đá quý pg vào dự án.

Bây giờ ta đã tham chiếu đến các biến môi trường của bạn , ta có thể tạo file cho chúng với các cài đặt ưa thích của ta . Extract cài đặt cấu hình theo cách này là một phần của cách tiếp cận 12 Yếu tố để phát triển ứng dụng, xác định các phương pháp hay nhất để có khả năng phục hồi ứng dụng trong môi trường phân tán. Bây giờ, khi ta đang cài đặt môi trường production và thử nghiệm của bạn trong tương lai, việc cấu hình cài đặt database của ta sẽ liên quan đến việc tạo file .env bổ sung và tham chiếu file thích hợp trong file Docker Compose của ta .

Mở file .env :

  • nano .env

Thêm các giá trị sau vào file :

~ / rails-docker / .env
DATABASE_NAME=rails_development DATABASE_USER=sammy DATABASE_PASSWORD=shark DATABASE_HOST=database REDIS_HOST=redis 

Ngoài việc đặt tên database , user và password của ta , ta cũng đã đặt một giá trị cho DATABASE_HOST . Giá trị, database , đề cập đến dịch vụ PostgreSQL database mà ta sẽ tạo bằng Docker Compose. Ta cũng đã đặt REDIS_HOST để chỉ định dịch vụ redis của ta .

Lưu file khi bạn hoàn tất chỉnh sửa.

Để tạo user database sammy , ta có thể viết một tập lệnh init.sql mà sau đó ta có thể mount vào containers database khi nó khởi động.

Mở file tập lệnh:

  • nano init.sql

Thêm mã sau để tạo user sammy có quyền quản trị:

~ / rails-docker / init.sql
CREATE USER sammy; ALTER USER sammy WITH SUPERUSER; 

Tập lệnh này sẽ tạo user thích hợp trên database và cấp cho user này các quyền quản trị.

Đặt quyền thích hợp trên tập lệnh:

  • chmod +x init.sql

Tiếp theo, ta sẽ cấu hình Sidekiq để hoạt động với dịch vụ redis chứa trong containers của ta . Ta có thể thêm một trình khởi tạo vào folder config/initializers , nơi Rails tìm kiếm các cài đặt cấu hình khi các khung và plugin được tải, điều này đặt giá trị cho server Redis.

Mở file sidekiq.rb để chỉ định các cài đặt này:

  • nano config/initializers/sidekiq.rb

Thêm mã sau vào file để chỉ định giá trị cho REDIS_HOSTREDIS_PORT :

~ / rails-docker / config / initializers / sidekiq.rb
Sidekiq.configure_server do |config|   config.redis = {     host: ENV['REDIS_HOST'],     port: ENV['REDIS_PORT'] || '6379'   } end  Sidekiq.configure_client do |config|   config.redis = {     host: ENV['REDIS_HOST'],     port: ENV['REDIS_PORT'] || '6379'   } end 

Giống như cài đặt cấu hình database của ta , những cài đặt này cho ta khả năng đặt động các thông số server và cổng, cho phép ta thay thế các giá trị thích hợp trong thời gian chạy mà không cần phải sửa đổi chính mã ứng dụng. Ngoài REDIS_HOST , ta có một giá trị mặc định được đặt cho REDIS_PORT trong trường hợp nó không được đặt ở nơi khác.

Lưu file khi bạn hoàn tất chỉnh sửa.

Tiếp theo, đảm bảo rằng dữ liệu nhạy cảm của ứng dụng của ta không bị sao chép sang kiểm soát version , ta có thể thêm .env vào file .gitignore của dự án, file này sẽ cho Git biết những file nào cần bỏ qua trong dự án của ta . Mở file để chỉnh sửa:

  • nano .gitignore

Ở cuối file , hãy thêm một mục nhập cho .env :

~ / rails-docker / .gitignore
yarn-debug.log* .yarn-integrity .env 

Lưu file khi bạn hoàn tất chỉnh sửa.

Tiếp theo, ta sẽ tạo một file .dockerignore để đặt những gì không nên sao chép vào containers của ta . Mở file để chỉnh sửa:

  • .dockerignore

Thêm mã sau vào file , mã này yêu cầu Docker bỏ qua một số thứ ta không cần sao chép vào containers của bạn :

~ / rails-docker / .dockerignore
.DS_Store .bin .git .gitignore .bundleignore .bundle .byebug_history .rspec tmp log test config/deploy public/packs public/packs-test node_modules yarn-error.log coverage/ 

Thêm .env vào cuối file này:

~ / rails-docker / .dockerignore
. . . yarn-error.log coverage/ .env 

Lưu file khi bạn hoàn tất chỉnh sửa.

Bước cuối cùng, ta sẽ tạo một số dữ liệu hạt giống để ứng dụng của ta có một vài bản ghi khi ta khởi động nó.

Mở file cho dữ liệu hạt giống trong folder db :

  • nano db/seeds.rb

Thêm mã sau vào file để tạo bốn con cá mập demo và một bài đăng mẫu:

~ / rails-docker / db / seed.rb
# Adding demo sharks sharks = Shark.create([{ name: 'Great White', facts: 'Scary' }, { name: 'Megalodon', facts: 'Ancient' }, { name: 'Hammerhead', facts: 'Hammer-like' }, { name: 'Speartooth', facts: 'Endangered' }]) Post.create(body: 'These sharks are misunderstood', shark: sharks.first) 

Dữ liệu hạt giống này sẽ tạo ra bốn con cá mập và một bài đăng được liên kết với con cá mập đầu tiên.

Lưu file khi bạn hoàn tất chỉnh sửa.

Với ứng dụng của bạn được cấu hình để hoạt động với PostgreSQL và các biến môi trường của bạn đã được tạo, bạn đã sẵn sàng để viết Dockerfile cho ứng dụng của bạn .

Bước 3 - Viết Tập lệnh Dockerfile và Entrypoint

Docker file chỉ định những gì sẽ được đưa vào containers ứng dụng của bạn khi nó được tạo. Sử dụng Dockerfile cho phép bạn xác định môi trường containers của bạn và tránh sự khác biệt với các version phụ thuộc hoặc thời gian chạy.

Tuân theo các nguyên tắc này về xây dựng các containers được tối ưu hóa , ta sẽ làm cho hình ảnh của bạn hiệu quả nhất có thể bằng cách sử dụng đế Alpine và cố gắng thu nhỏ các lớp hình ảnh của ta nói chung.

Mở file Dockerfile trong folder hiện tại của bạn:

  • nano Dockerfile

Docker image được tạo bằng cách sử dụng liên tiếp các hình ảnh nhiều lớp xây dựng trên nhau. Bước đầu tiên của ta sẽ là thêm hình ảnh cơ sở cho ứng dụng của ta , hình ảnh này sẽ tạo thành điểm bắt đầu của việc xây dựng ứng dụng.

Thêm mã sau vào file để thêm hình ảnh núi cao Ruby làm cơ sở:

~ / rails-docker / Dockerfile
FROM ruby:2.5.1-alpine 

Hình ảnh alpine có nguồn root từ dự án Alpine Linux và sẽ giúp ta giảm kích thước hình ảnh. Để biết thêm thông tin về việc liệu hình ảnh alpine có phải là sự lựa chọn phù hợp cho dự án của bạn hay không, vui lòng xem toàn bộ cuộc thảo luận trong phần Biến thể Hình ảnh của trang Docker image Hub Ruby .

Một số yếu tố cần xem xét khi sử dụng alpine trong phát triển:

  • Giảm kích thước hình ảnh sẽ làm giảm thời gian tải trang và tài nguyên, đặc biệt nếu bạn cũng giữ dung lượng ở mức tối thiểu. Điều này giúp giữ cho trải nghiệm user của bạn phát triển nhanh chóng và gần hơn với những gì sẽ xảy ra nếu bạn đang làm việc local trong môi trường không chứa đựng.
  • Có sự tương đương giữa hình ảnh phát triển và production tạo điều kiện cho việc triển khai thành công. Vì các group thường chọn sử dụng hình ảnh Alpine trong quá trình production vì lợi ích về tốc độ, nên việc phát triển với đế Alpine giúp giải quyết các vấn đề khi chuyển sang production .

Tiếp theo, đặt một biến môi trường để chỉ định version Bundler :

~ / rails-docker / Dockerfile
. . . ENV BUNDLER_VERSION=2.0.2 

Đây là một trong những bước ta sẽ thực hiện để tránh xung đột version giữa version bundler mặc định có sẵn trong môi trường của ta và mã ứng dụng của ta , yêu cầu Bundler 2.0.2.

Tiếp theo, thêm các gói mà bạn cần để làm việc với ứng dụng vào Dockerfile:

~ / rails-docker / Dockerfile
. . .  RUN apk add --update --no-cache \       binutils-gold \       build-base \       curl \       file \       g++ \       gcc \       git \       less \       libstdc++ \       libffi-dev \       libc-dev \        linux-headers \       libxml2-dev \       libxslt-dev \       libgcrypt-dev \       make \       netcat-openbsd \       nodejs \       openssl \       pkgconfig \       postgresql-dev \       python \       tzdata \       yarn  

Các gói này bao gồm nodejsyarn , trong số những gói khác. Vì ứng dụng của ta cung cấp nội dung với webpack , ta cần bao gồm Node.jsYarn để ứng dụng hoạt động như mong đợi.

Lưu ý hình ảnh alpine cực kỳ tối thiểu: các gói được liệt kê ở đây không đầy đủ những gì bạn có thể cần hoặc cần trong quá trình phát triển khi bạn đang chứa ứng dụng của riêng mình.

Tiếp theo, cài đặt version bundler thích hợp:

~ / rails-docker / Dockerfile
. . .  RUN gem install bundler -v 2.0.2 

Bước này sẽ đảm bảo tính ngang bằng giữa môi trường được container của ta và các thông số kỹ thuật trong file Gemfile.lock của dự án này.

Bây giờ đặt folder làm việc cho ứng dụng trên containers :

~ / rails-docker / Dockerfile
. . . WORKDIR /app 

Sao chép của bạn GemfileGemfile.lock :

~ / rails-docker / Dockerfile
. . . COPY Gemfile Gemfile.lock ./ 

Sao chép các file này như một bước độc lập, sau đó là bundle install , nghĩa là các viên ngọc dự án không cần phải được xây dựng lại mỗi khi bạn thực hiện thay đổi đối với mã ứng dụng của bạn . Điều này sẽ hoạt động cùng với dung lượng đá quý mà ta sẽ đưa vào file Soạn của bạn , sẽ gắn đá quý vào containers ứng dụng của bạn trong trường hợp dịch vụ được tạo lại nhưng đá quý của dự án vẫn giữ nguyên.

Tiếp theo, đặt các tùy chọn cấu hình cho bản dựng đá quý nokogiri :

~ / rails-docker / Dockerfile
. . .  RUN bundle config build.nokogiri --use-system-libraries . . . 

Bước này xây dựng nokigiri với các version thư viện libxml2libxslt mà ta đã thêm vào containers ứng dụng trong RUN apk add… bước trên.

Tiếp theo, cài đặt các gem của dự án:

~ / rails-docker / Dockerfile
. . .  RUN bundle check || bundle install 

Hướng dẫn này kiểm tra xem đá quý chưa được cài đặt trước khi cài đặt chúng.

Tiếp theo, ta sẽ lặp lại quy trình tương tự mà ta đã sử dụng với đá quý với các gói và phụ thuộc JavaScript của ta . Đầu tiên, ta sẽ sao chép metadata gói, sau đó ta sẽ cài đặt các phần phụ thuộc và cuối cùng ta sẽ sao chép mã ứng dụng vào containers images .

Để bắt đầu với phần Javascript trong Dockerfile của ta , hãy sao chép package.jsonyarn.lock từ folder dự án hiện tại của bạn trên server lưu trữ vào containers :

~ / rails-docker / Dockerfile
. . .  COPY package.json yarn.lock ./ 

Sau đó, cài đặt các gói yêu cầu với yarn install :

~ / rails-docker / Dockerfile
. . .  RUN yarn install --check-files 

Hướng dẫn này bao gồm --check-files với lệnh yarn , một tính năng đảm bảo mọi file đã cài đặt trước đó không bị xóa. Như trong trường hợp các node_modules của ta , ta sẽ quản lý sự tồn tại của các gói trong folder node_modules bằng một ổ đĩa khi ta viết file Soạn của bạn .

Cuối cùng, sao chép phần còn lại của mã ứng dụng và khởi động ứng dụng với một đoạn mã entrypoint:

~ / rails-docker / Dockerfile
. . .  COPY . ./   ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"] 

Sử dụng một tập lệnh entrypoint cho phép ta chạy containers dưới dạng file thực thi .

Dockerfile cuối cùng sẽ giống như sau:

~ / rails-docker / Dockerfile
FROM ruby:2.5.1-alpine  ENV BUNDLER_VERSION=2.0.2  RUN apk add --update --no-cache \       binutils-gold \       build-base \       curl \       file \       g++ \       gcc \       git \       less \       libstdc++ \       libffi-dev \       libc-dev \        linux-headers \       libxml2-dev \       libxslt-dev \       libgcrypt-dev \       make \       netcat-openbsd \       nodejs \       openssl \       pkgconfig \       postgresql-dev \       python \       tzdata \       yarn   RUN gem install bundler -v 2.0.2  WORKDIR /app  COPY Gemfile Gemfile.lock ./  RUN bundle config build.nokogiri --use-system-libraries  RUN bundle check || bundle install   COPY package.json yarn.lock ./  RUN yarn install --check-files  COPY . ./   ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"] 

Lưu file khi bạn hoàn tất chỉnh sửa.

Tiếp theo, tạo một folder có tên là entrypoints cho các tập lệnh entrypoint:

  • mkdir entrypoints

Thư mục này sẽ bao gồm tập lệnh entrypoint chính của ta và một tập lệnh cho dịch vụ Sidekiq của ta .

Mở file cho tập lệnh điểm nhập ứng dụng:

  • nano entrypoints/docker-entrypoint.sh

Thêm mã sau vào file :

rails-docker / entrypoints / docker-entrypoint.sh
#!/bin/sh  set -e  if [ -f tmp/pids/server.pid ]; then   rm tmp/pids/server.pid fi  bundle exec rails s -b 0.0.0.0 

Dòng quan trọng đầu tiên là set -e , cho biết shell /bin/sh chạy tập lệnh bị lỗi nhanh nếu có sự cố nào sau này trong tập lệnh. Tiếp theo, tập lệnh kiểm tra xem tmp/pids/server.pid không có mặt đảm bảo rằng sẽ không có xung đột server khi ta khởi động ứng dụng. Cuối cùng, tập lệnh khởi động server Rails bằng lệnh bundle exec rails s . Ta sử dụng tùy chọn -b với lệnh này để liên kết server với tất cả các địa chỉ IP thay vì với localhost , mặc định. Lệnh gọi này làm cho server Rails định tuyến các yêu cầu đến IP containers thay vì đến localhost mặc định.

Lưu file khi bạn hoàn tất chỉnh sửa.

Làm cho tập lệnh có thể thực thi:

  • chmod +x entrypoints/docker-entrypoint.sh

Tiếp theo, ta sẽ tạo một tập lệnh để bắt đầu dịch vụ sidekiq của ta , dịch vụ này sẽ xử lý các công việc Sidekiq của ta . Để biết thêm thông tin về cách ứng dụng này sử dụng Sidekiq, vui lòng xem Cách thêm Sidekiq và Redis vào Ứng dụng Ruby on Rails .

Mở file cho tập lệnh điểm nhập Sidekiq:

  • nano entrypoints/sidekiq-entrypoint.sh

Thêm mã sau vào file để bắt đầu Sidekiq:

~ / rails-docker / entrypoints / sidekiq-entrypoint.sh
#!/bin/sh  set -e  if [ -f tmp/pids/server.pid ]; then   rm tmp/pids/server.pid fi  bundle exec sidekiq 

Tập lệnh này khởi động Sidekiq trong bối cảnh gói ứng dụng của ta .

Lưu file khi bạn hoàn tất chỉnh sửa. Làm cho nó có thể thực thi:

  • chmod +x entrypoints/sidekiq-entrypoint.sh

Với các tập lệnh entrypoint và Dockerfile tại chỗ, bạn đã sẵn sàng xác định các dịch vụ của bạn trong file Soạn của bạn .

Bước 4 - Xác định Dịch vụ với Docker Compose

Sử dụng Docker Compose, ta sẽ có thể chạy nhiều containers cần thiết cho cài đặt của ta . Ta sẽ xác định các dịch vụ Soạn thư của bạn trong file docker-compose.yml chính của ta . Dịch vụ trong Soạn là một containers đang chạy và các định nghĩa dịch vụ - mà bạn sẽ đưa vào file docker-compose.yml - chứa thông tin về cách mỗi containers images sẽ chạy. Công cụ Soạn thư cho phép bạn xác định nhiều dịch vụ để xây dựng các ứng dụng đa containers .

Cài đặt ứng dụng của ta sẽ bao gồm các dịch vụ sau:

  • Bản thân ứng dụng
  • Database PostgreSQL
  • Redis
  • Sidekiq

Ta cũng sẽ bao gồm một mount liên kết như một phần của cài đặt của ta , để bất kỳ thay đổi mã nào ta thực hiện trong quá trình phát triển sẽ được đồng bộ hóa ngay lập tức với các containers cần quyền truy cập vào mã này.

Lưu ý ta không xác định dịch vụ test , vì thử nghiệm nằm ngoài phạm vi của hướng dẫn và loạt bài này , nhưng bạn có thể làm như vậy theo tiền lệ mà ta đang sử dụng ở đây cho dịch vụ sidekiq .

Mở file docker-compose.yml :

  • nano docker-compose.yml

Đầu tiên, hãy thêm định nghĩa dịch vụ ứng dụng:

~ / rails-docker / docker-compost.yml
version: '3.4'  services:   app:      build:       context: .       dockerfile: Dockerfile     depends_on:       - database       - redis     ports:        - "3000:3000"     volumes:       - .:/app       - gem_cache:/usr/local/bundle/gems       - node_modules:/app/node_modules     env_file: .env     environment:       RAILS_ENV: development 

Định nghĩa dịch vụ app bao gồm các tùy chọn sau:

  • build : Tùy chọn này xác định các tùy chọn cấu hình, bao gồm contextdockerfile , sẽ được áp dụng khi Compose xây dựng hình ảnh ứng dụng. Nếu bạn muốn sử dụng hình ảnh hiện có từ một nơi đăng ký như Docker Hub , bạn có thể sử dụng hướng dẫn image thay thế, với thông tin về tên user , repository và thẻ hình ảnh của bạn.
  • context : Điều này xác định bối cảnh xây dựng cho bản dựng hình ảnh - trong trường hợp này là folder dự án hiện tại.
  • dockerfile : Điều này chỉ định Dockerfile trong folder dự án hiện tại của bạn làm file Compose sẽ sử dụng để xây dựng hình ảnh ứng dụng.
  • depends_on : Điều này cài đặt databaseredis container trước để chúng được cài đặt và chạy trước app .
  • ports : Điều này ánh xạ cổng 3000 trên server đến cổng 3000 trên containers .
  • volumes : Ta bao gồm hai loại mount ở đây:
    • Đầu tiên là một liên kết ràng buộc gắn mã ứng dụng của ta trên server lưu trữ vào folder /app trên containers . Điều này sẽ tạo điều kiện phát triển nhanh chóng, vì bất kỳ thay đổi nào bạn thực hiện đối với mã server của bạn sẽ được điền ngay vào containers .
    • Thứ hai là một tên dung lượng , gem_cache . Khi hướng dẫn bundle install chạy trong containers , nó sẽ cài đặt các viên ngọc của dự án. Thêm dung lượng này nghĩa là nếu bạn tạo lại containers , các viên ngọc sẽ được gắn vào containers mới. Mount này giả định không có bất kỳ thay đổi nào đối với dự án, vì vậy nếu bạn thực hiện thay đổi đối với các viên ngọc dự án của bạn trong quá trình phát triển, bạn cần nhớ xóa tập này trước khi tạo lại dịch vụ ứng dụng của bạn .
    • Tập thứ ba là một tập được đặt tên cho folder node_modules . Thay vì có node_modules được gắn vào server , điều này có thể dẫn đến sự khác biệt về gói và xung đột quyền trong quá trình phát triển, tập này sẽ đảm bảo các gói trong folder này vẫn tồn tại và phản ánh trạng thái hiện tại của dự án. , nếu bạn sửa đổi các phụ thuộc Node của dự án, bạn cần phải xóa và tạo lại ổ đĩa này.
  • env_file : Điều này cho Soạn biết rằng ta muốn thêm các biến môi trường từ một file có tên .env nằm trong ngữ cảnh xây dựng.
  • environment : Sử dụng tùy chọn này cho phép ta cài đặt một biến môi trường không nhạy cảm, truyền thông tin về môi trường Rails vào containers .

Tiếp theo, bên dưới định nghĩa dịch vụ app , hãy thêm mã sau để xác định dịch vụ database của bạn:

~ / rails-docker / docker-compost.yml
. . .   database:     image: postgres:12.1     volumes:       - db_data:/var/lib/postgresql/data       - ./init.sql:/docker-entrypoint-initdb.d/init.sql 

Không giống như dịch vụ app , dịch vụ database lấy một hình ảnh postgres trực tiếp từ Docker Hub . Lưu ý ta cũng đang ghim version ở đây, thay vì đặt nó thành latest hoặc không chỉ định nó (mặc định là latest ). Bằng cách này, ta có thể đảm bảo cài đặt này hoạt động với các version được chỉ định ở đây và tránh những bất ngờ không mong muốn với các thay đổi mã vi phạm đối với hình ảnh.

Ta cũng bao gồm một db_data ở đây, ổ đĩa này sẽ duy trì dữ liệu ứng dụng của ta giữa các lần khởi động containers . Ngoài ra, ta đã gắn tập lệnh khởi động init.sql của bạn vào folder thích hợp, docker-entrypoint-initdb.d/ trên containers , để tạo user database sammy của ta . Sau khi điểm nhập hình ảnh tạo database và user postgres mặc định, nó sẽ chạy bất kỳ tập lệnh nào được tìm thấy trong folder docker-entrypoint-initdb.d/ mà bạn có thể sử dụng cho các việc khởi tạo cần thiết. Để biết thêm chi tiết, hãy xem phần Tập lệnh khởi tạo của tài liệu hình ảnh PostgreSQL

Tiếp theo, thêm định nghĩa dịch vụ redis :

~ / rails-docker / docker-compost.yml
. . .   redis:     image: redis:5.0.7 

Giống như dịch vụ database , dịch vụ redis sử dụng hình ảnh từ Docker Hub. Trong trường hợp này, ta không duy trì bộ nhớ cache công việc Sidekiq.

Cuối cùng, thêm định nghĩa dịch vụ sidekiq :

~ / rails-docker / docker-compost.yml
. . .   sidekiq:     build:       context: .       dockerfile: Dockerfile     depends_on:       - app             - database       - redis     volumes:       - .:/app       - gem_cache:/usr/local/bundle/gems       - node_modules:/app/node_modules     env_file: .env     environment:       RAILS_ENV: development     entrypoint: ./entrypoints/sidekiq-entrypoint.sh 

Dịch vụ sidekiq của ta giống với dịch vụ app của ta ở một số khía cạnh: nó sử dụng cùng một bối cảnh và hình ảnh xây dựng, các biến môi trường và dung lượng . Tuy nhiên, nó phụ thuộc vào app , redis và các dịch vụ database và vì vậy sẽ là lần cuối cùng bắt đầu. Ngoài ra, nó sử dụng một entrypoint sẽ overrides điểm nhập được đặt trong Dockerfile. Cài đặt entrypoint này trỏ tới entrypoints/sidekiq-entrypoint.sh , bao gồm lệnh thích hợp để khởi động dịch vụ sidekiq .

Bước cuối cùng, hãy thêm định nghĩa âm lượng bên dưới định nghĩa dịch vụ sidekiq :

~ / rails-docker / docker-compost.yml
. . . volumes:   gem_cache:   db_data:   node_modules: 

Khóa dung lượng cấp cao nhất của ta xác định các dung lượng gem_cache , db_datanode_modules . Khi Docker tạo tập, nội dung của tập được lưu trữ trong một phần của hệ thống file server , /var/lib/docker/volumes/ , được Docker quản lý. Nội dung của mỗi tập được lưu trữ trong một folder dưới /var/lib/docker/volumes/ và được gắn vào bất kỳ containers nào sử dụng tập. Bằng cách này, dữ liệu thông tin cá mập mà user của ta sẽ tạo sẽ tồn tại trong db_data ngay cả khi ta xóa và tạo lại dịch vụ database .

Tệp đã hoàn thành sẽ giống như sau:

~ / rails-docker / docker-compost.yml
version: '3.4'  services:   app:      build:       context: .       dockerfile: Dockerfile     depends_on:            - database       - redis     ports:        - "3000:3000"     volumes:       - .:/app       - gem_cache:/usr/local/bundle/gems       - node_modules:/app/node_modules     env_file: .env     environment:       RAILS_ENV: development    database:     image: postgres:12.1     volumes:       - db_data:/var/lib/postgresql/data       - ./init.sql:/docker-entrypoint-initdb.d/init.sql    redis:     image: redis:5.0.7    sidekiq:     build:       context: .       dockerfile: Dockerfile     depends_on:       - app             - database       - redis     volumes:       - .:/app       - gem_cache:/usr/local/bundle/gems       - node_modules:/app/node_modules     env_file: .env     environment:       RAILS_ENV: development     entrypoint: ./entrypoints/sidekiq-entrypoint.sh  volumes:   gem_cache:   db_data:   node_modules:      

Lưu file khi bạn hoàn tất chỉnh sửa.

Với các định nghĩa dịch vụ của bạn đã được viết sẵn, bạn đã sẵn sàng khởi động ứng dụng.

Bước 5 - Kiểm tra ứng dụng

Với file docker-compose.yml của bạn tại chỗ, bạn có thể tạo các dịch vụ của bạn bằng lệnh docker-compose up database của bạn. Bạn cũng có thể kiểm tra xem dữ liệu của bạn có tồn tại hay không bằng cách dừng và xóa các containers của bạn bằng docker-compose down chúng.

Đầu tiên, xây dựng các containers images và tạo các dịch vụ bằng cách chạy docker-compose up với cờ -d , sẽ chạy các containers trong nền:

  • docker-compose up -d

Bạn sẽ thấy kết quả rằng các dịch vụ của bạn đã được tạo:

Output
Creating rails-docker_database_1 ... done Creating rails-docker_redis_1 ... done Creating rails-docker_app_1 ... done Creating rails-docker_sidekiq_1 ... done

Bạn cũng có thể nhận thêm thông tin chi tiết về các quy trình khởi động bằng cách hiển thị kết quả log từ các dịch vụ:

  • docker-compose logs

Bạn sẽ thấy thông tin như thế này nếu mọi thứ đã bắt đầu đúng :

Output
sidekiq_1 | 2019-12-19T15:05:26.365Z pid=6 tid=grk7r6xly INFO: Booting Sidekiq 6.0.3 with redis options {:host=>"redis", :port=>"6379", :id=>"Sidekiq-server-PID-6", :url=>nil} sidekiq_1 | 2019-12-19T15:05:31.097Z pid=6 tid=grk7r6xly INFO: Running in ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-musl] sidekiq_1 | 2019-12-19T15:05:31.097Z pid=6 tid=grk7r6xly INFO: See LICENSE and the LGPL-3.0 for licensing details. sidekiq_1 | 2019-12-19T15:05:31.097Z pid=6 tid=grk7r6xly INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org app_1 | => Booting Puma app_1 | => Rails 5.2.3 application starting in development app_1 | => Run `rails server -h` for more startup options app_1 | Puma starting in single mode... app_1 | * Version 3.12.1 (ruby 2.5.1-p57), codename: Llamas in Pajamas app_1 | * Min threads: 5, max threads: 5 app_1 | * Environment: development app_1 | * Listening on tcp://0.0.0.0:3000 app_1 | Use Ctrl-C to stop . . . database_1 | PostgreSQL init process complete; ready for start up. database_1 | database_1 | 2019-12-19 15:05:20.160 UTC [1] LOG: starting PostgreSQL 12.1 (Debian 12.1-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit database_1 | 2019-12-19 15:05:20.160 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432 database_1 | 2019-12-19 15:05:20.160 UTC [1] LOG: listening on IPv6 address "::", port 5432 database_1 | 2019-12-19 15:05:20.163 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" database_1 | 2019-12-19 15:05:20.182 UTC [63] LOG: database system was shut down at 2019-12-19 15:05:20 UTC database_1 | 2019-12-19 15:05:20.187 UTC [1] LOG: database system is ready to accept connections . . . redis_1 | 1:M 19 Dec 2019 15:05:18.822 * Ready to accept connections

Bạn cũng có thể kiểm tra trạng thái của các containers của bạn bằng docker-compose ps :

  • docker-compose ps

Bạn sẽ thấy kết quả cho biết rằng các containers của bạn đang chạy:

Output
Name Command State Ports ----------------------------------------------------------------------------------------- rails-docker_app_1 ./entrypoints/docker-resta ... Up 0.0.0.0:3000->3000/tcp rails-docker_database_1 docker-entrypoint.sh postgres Up 5432/tcp rails-docker_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp rails-docker_sidekiq_1 ./entrypoints/sidekiq-entr ... Up

Tiếp theo, tạo và khởi tạo database của bạn và chạy quá trình di chuyển trên đó bằng lệnh thực thi docker-compose exec sau:

  • docker-compose exec app bundle exec rake db:setup db:migrate

Lệnh thực thi docker-compose exec cho phép bạn chạy các lệnh trong các dịch vụ của bạn ; ta đang sử dụng nó ở đây để chạy rake db:setupdb:migrate trong bối cảnh gói ứng dụng của ta để tạo và khởi tạo database và chạy di chuyển. Khi bạn làm việc trong quá trình phát triển, trình điều khiển docker-compose exec sẽ tỏ ra hữu ích cho bạn khi bạn muốn chạy di chuyển đối với database phát triển của bạn .

Bạn sẽ thấy kết quả sau khi chạy lệnh này:

Output
Created database 'rails_development' Database 'rails_development' already exists -- enable_extension("plpgsql") -> 0.0140s -- create_table("endangereds", {:force=>:cascade}) -> 0.0097s -- create_table("posts", {:force=>:cascade}) -> 0.0108s -- create_table("sharks", {:force=>:cascade}) -> 0.0050s -- enable_extension("plpgsql") -> 0.0173s -- create_table("endangereds", {:force=>:cascade}) -> 0.0088s -- create_table("posts", {:force=>:cascade}) -> 0.0128s -- create_table("sharks", {:force=>:cascade}) -> 0.0072s

Khi các dịch vụ của bạn đang chạy, bạn có thể truy cập localhost:3000 hoặc http://your_server_ip:3000 trong trình duyệt. Bạn sẽ thấy một trang đích giống như sau:

Trang chủ ứng dụng Sidekiq

Bây giờ ta có thể kiểm tra độ bền của dữ liệu. Tạo một con cá mập mới bằng cách nhấp vào nút Nhận thông tin cá mập , nút này sẽ đưa bạn đến tuyến đường sharks/index :

Trang index  cá mập với dữ liệu được hạt giống

Để xác minh ứng dụng đang hoạt động, ta có thể thêm một số thông tin demo vào nó. Nhấp vào Cá mập mới . Bạn sẽ được yêu cầu nhập tên user ( sammy ) và password ( cá mập ), nhờ cài đặt xác thực của dự án.

Trên trang Cá mập mới , nhập “Mako” vào trường Tên và “Nhanh” vào trường Dữ kiện .

Nhấn vào nút Create Shark để tạo cá mập. Khi bạn đã tạo xong con cá mập, hãy nhấp vào Trang chủ trên thanh chuyển của trang web để quay lại trang đích của ứng dụng chính. Bây giờ ta có thể kiểm tra Sidekiq đang hoạt động.

Nhấp vào Cá mập nào đang gặp nguy hiểm? cái nút. Vì bạn chưa tải lên bất kỳ loài cá mập nguy cấp nào nên điều này sẽ đưa bạn đến chế độ xem index endangered :

Chế độ xem index  nguy cấp

Nhấp vào Nhập cá mập nguy cấp để nhập cá mập. Bạn sẽ thấy một thông báo trạng thái cho bạn biết rằng cá mập đã được nhập:

Bắt đầu nhập

Bạn cũng sẽ thấy phần bắt đầu của quá trình nhập. Làm mới trang web để xem toàn bộ bảng:

Làm mới bảng

Nhờ Sidekiq, quá trình tải lên hàng loạt lớn về cá mập có nguy cơ tuyệt chủng của ta đã thành công mà không cần khóa trình duyệt hoặc can thiệp vào chức năng ứng dụng khác.

Nhấp vào nút Trang chủ ở cuối trang, nút này sẽ đưa bạn trở lại trang chính của ứng dụng:

Trang chủ ứng dụng Sidekiq

Từ đây, nhấp vào Cá mập nào đang gặp nguy hiểm? lần nữa. Bạn sẽ nhìn thấy những con cá mập được tải lên .

Bây giờ ta biết ứng dụng của bạn đang hoạt động bình thường, ta có thể kiểm tra tính bền bỉ của dữ liệu.

Quay lại terminal của bạn, nhập lệnh sau để dừng và xóa các containers của bạn:

  • docker-compose down

Lưu ý ta không bao gồm tùy chọn --volumes ; do đó, dung lượng db_data của ta không bị xóa.

Kết quả sau xác nhận containers và mạng của bạn đã bị xóa:

Output
Stopping rails-docker_sidekiq_1 ... done Stopping rails-docker_app_1 ... done Stopping rails-docker_database_1 ... done Stopping rails-docker_redis_1 ... done Removing rails-docker_sidekiq_1 ... done Removing rails-docker_app_1 ... done Removing rails-docker_database_1 ... done Removing rails-docker_redis_1 ... done Removing network rails-docker_default

Tạo lại các containers :

  • docker-compose up -d

Mở console Rails trên containers app với console thực thi docker-compose execbundle exec rails console :

  • docker-compose exec app bundle exec rails console

Khi được yêu cầu , hãy kiểm tra bản ghi Shark last trong database :

  • Shark.last.inspect

Bạn sẽ thấy bản ghi bạn vừa tạo:

IRB session
Shark Load (1.0ms) SELECT "sharks".* FROM "sharks" ORDER BY "sharks"."id" DESC LIMIT $1 [["LIMIT", 1]] => "#<Shark id: 5, name: \"Mako\", facts: \"Fast\", created_at: \"2019-12-20 14:03:28\", updated_at: \"2019-12-20 14:03:28\">"

Sau đó, bạn có thể kiểm tra xem những con Cá mập Endangered của bạn vẫn còn tồn tại bằng lệnh sau:

  • Endangered.all.count
IRB session
(0.8ms) SELECT COUNT(*) FROM "endangereds" => 73

db_data của bạn đã được mount thành công vào dịch vụ database tạo lại, giúp dịch vụ app của bạn có thể truy cập vào dữ liệu đã lưu. Nếu bạn chuyển trực tiếp đến trang shark index bằng cách truy cập localhost:3000/sharks shark hoặc http://your_server_ip:3000/sharks bạn cũng sẽ thấy bản ghi đó được hiển thị:

Trang index  cá mập với Mako

Những con cá mập có nguy cơ tuyệt chủng của bạn cũng sẽ có tại localhost:3000/endangered/data http://your_server_ip:3000/endangered/data localhost:3000/endangered/data hoặc http://your_server_ip:3000/endangered/data view:

Làm mới bảng

Ứng dụng của bạn hiện đang chạy trên containers Docker với tính năng ổn định dữ liệu và đồng bộ hóa mã được bật. Bạn có thể tiếp tục và kiểm tra các thay đổi mã local trên server của bạn , các thay đổi này sẽ được đồng bộ hóa với containers của bạn nhờ mount liên kết mà ta đã xác định là một phần của dịch vụ app .

Kết luận

Theo hướng dẫn này, bạn đã tạo một cài đặt phát triển cho ứng dụng Rails của bạn bằng cách sử dụng Docker container. Bạn đã làm cho dự án của bạn mang tính mô-đun và di động hơn bằng cách extract thông tin nhạy cảm và tách trạng thái ứng dụng khỏi mã của bạn. Bạn cũng đã cấu hình một file docker-compose.yml mà bạn có thể sửa đổi khi nhu cầu phát triển và yêu cầu của bạn thay đổi.

Khi bạn phát triển, bạn có thể quan tâm đến việc tìm hiểu thêm về cách thiết kế các ứng dụng cho quy trình làm việc được chứa trong container và Cloud Native . Vui lòng xemỨng dụng kiến trúc cho KubernetesỨng dụng hiện đại hóa cho Kubernetes để biết thêm thông tin về các chủ đề này. Hoặc, nếu bạn muốn đầu tư vào trình tự học Kubernetes, vui lòng xem qua giáo trình Kubernetes dành cho Nhà phát triển toàn ngăn xếp .

Để tìm hiểu thêm về mã ứng dụng, vui lòng xem các hướng dẫn khác trong loạt bài này:


Tags:

Các tin liên quan

Làm việc với nhiều container bằng Docker Compose
2019-12-20
Cách sử dụng Plugin Docker cho Visual Studio Code
2019-12-12
Cách sử dụng Ansible để cài đặt và thiết lập Docker trên Ubuntu 18.04
2019-12-05
Cách tạo ứng dụng Django và Gunicorn với Docker
2019-10-25
Cách thiết lập Flask với MongoDB và Docker
2019-10-11
Cách cài đặt và sử dụng Docker trên Debian 10
2019-07-08
Cách sử dụng server Docker từ xa để tăng tốc quy trình làm việc của bạn
2019-06-25
Cách cài đặt WordPress với Docker Compose
2019-05-24
Cách di chuyển Docker compose workflow sang Kubernetes
2019-04-03
Cách tối ưu hóa image Docker cho sản xuất
2019-03-25