Việc Docker hóa Ruby on Rails của bạn bằng ứng dụng giao diện người dùng React có thể cải thiện đáng kể quy trình phát triển và quy trình triển khai của bạn. Bằng cách tạo môi trường tiêu chuẩn hóa cho ứng dụng của mình, bạn đảm bảo hành vi nhất quán trong các giai đoạn phát triển, thử nghiệm, sản xuất khác nhau và thậm chí trên các hệ thống khác nhau. Trên thực tế, nó được thiết kế để giảm thiểu các vấn đề liên quan đến sự khác biệt của hệ thống. Hướng dẫn này sẽ hướng dẫn bạn các bước cần thiết để giúp ứng dụng Rails và React của bạn chạy trơn tru trong vùng chứa Docker. Tại sao Dockerize một ứng dụng? : Tính nhất quán giữa các môi trường Docker đảm bảo rằng ứng dụng chạy theo cùng một cách bất kể nó được triển khai ở đâu, cho dù trên máy của nhà phát triển, môi trường thử nghiệm hay máy chủ sản xuất. Tính nhất quán này đạt được bằng cách chứa tất cả các phụ thuộc và cấu hình. : Quản lý phụ thuộc Bộ chứa Docker bao gồm tất cả các phần phụ thuộc cần thiết để ứng dụng chạy. Điều này có nghĩa là các biến thể trong thư viện hệ thống hoặc các phần phụ thuộc bị thiếu trên các hệ thống khác nhau không ảnh hưởng đến chức năng của ứng dụng. : Sự cách ly Các container Docker chạy độc lập với nhau và với hệ thống máy chủ. Sự cô lập này ngăn ngừa xung đột giữa các ứng dụng khác nhau và sự phụ thuộc của chúng trên cùng một hệ thống. : Tính di động Các bộ chứa Docker có thể dễ dàng di chuyển và chạy trên bất kỳ hệ thống nào hỗ trợ Docker, cho dù đó là máy cục bộ, dịch vụ đám mây hay máy chủ chuyên dụng. Điều này làm cho ứng dụng có tính di động cao và linh hoạt trong việc triển khai. Lưu ý: Cần có kiến thức về cú pháp Docker Dockerization liên quan đến hai khái niệm chính: hình ảnh và vùng chứa. Hình ảnh đóng vai trò là bản thiết kế cho vùng chứa, chứa tất cả thông tin cần thiết để tạo vùng chứa, bao gồm cả các phần phụ thuộc và cấu hình triển khai. Vùng chứa là một phiên bản thời gian chạy của một hình ảnh, bao gồm chính hình ảnh đó, môi trường thực thi và các hướng dẫn thời gian chạy. Docker nói chung thiết lập một tiêu chuẩn cho phần mềm vận chuyển. Để giải thích Docker bằng một phép tương tự đơn giản: hãy coi container là các container vận chuyển trong bãi, hình ảnh là các vật phẩm được đặt bên trong các container này và tàu vận chuyển là hệ thống mà các container chạy trên đó. Bất cứ khi nào bạn thiết lập và xây dựng ứng dụng của mình, cần phải có một số cấu hình môi trường nhất định. Ví dụ: bạn không thể chạy ứng dụng Rails nếu không cài đặt môi trường Ruby trên hệ thống của mình. Tương tự, bạn không thể chạy ứng dụng React mà không có và bạn không thể cài đặt các gói React mà không có trình quản lý gói Node như hoặc , v.v. Node.js npm Yarn Vì vùng chứa chạy tách biệt với hệ thống của người dùng nên chúng tôi sẽ cung cấp tất cả các gói này trong vùng chứa của mình giống như chúng tôi đã làm trong trường hợp chúng tôi xây dựng nó trực tiếp trên hệ thống của mình, do đó, vùng chứa sẽ hoạt động như một hệ thống trên đó sở hữu, giống như một máy ảo. Có sự khác biệt giữa docker và máy ảo nhưng ví dụ này chỉ nhằm giải thích thêm. Bây giờ, hãy tiếp tục và neo ứng dụng Rails. Để thực hiện việc này, chúng ta sẽ cần ba tệp trong ứng dụng Rails của mình: , và . Chúng ta hãy xem xét chi tiết từng tập tin này. Dockerfile docker-compose.yml bin/docker-entrypoint Lưu ý: Cần có kiến thức về cú pháp Docker Dockerfile là bản thiết kế chi tiết để tạo vùng chứa Docker. Nó chứa một loạt hướng dẫn mà Docker sử dụng để xây dựng một image, sau đó có thể được sử dụng để chạy các container. Hãy chia nhỏ cho ứng dụng Ruby on Rails và React: Dockerfile Dockerfile . Hình ảnh cơ sở ARG RUBY_VERSION=3.1.4 FROM ruby:$RUBY_VERSION : Xác định đối số bản dựng có tên với giá trị mặc định là . Điều này có thể được ghi đè tại thời điểm xây dựng. ARG RUBY_VERSION=3.1.4 RUBY_VERSION 3.1.4 : Sử dụng hình ảnh cơ sở với phiên bản được chỉ định bởi . Điều này sẽ thiết lập vùng chứa với thời gian chạy Ruby. Giống như tôi đã đề cập trước đó, để chạy ứng dụng Rails, bạn cần cài đặt Ruby. FROM ruby:$RUBY_VERSION ruby RUBY_VERSION 2. Cài đặt phụ thuộc RUN apt-get update -qq && \ apt-get install -y build-essential libvips bash bash-completion libffi-dev tzdata postgresql curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man : Cập nhật danh sách gói từ kho lưu trữ, với cho đầu ra yên tĩnh. apt-get update -qq -qq : Cài đặt các gói khác nhau: apt-get install -y ... : Các gói cần thiết để xây dựng phần mềm (như GCC). build-essential : Thư viện xử lý ảnh. libvips , : Bash shell và tính năng tự động hoàn thành của nó. bash bash-completion : Thư viện Giao diện chức năng nước ngoài. libffi-dev : Dữ liệu múi giờ. tzdata : Máy khách cơ sở dữ liệu PostgreSQL. postgresql : Công cụ chuyển dữ liệu từ URL. curl : Dọn dẹp kho lưu trữ cục bộ của các tệp gói được truy xuất. apt-get clean : Xóa danh sách gói và tài liệu để giảm kích thước hình ảnh. rm -rf /var/lib/apt/lists/ /usr/share/doc /usr/share/man 3. Cài đặt Node.js và Yarn RUN curl -fsSL https://deb.nodesource.com/setup_current.x | bash - && \ apt-get install -y nodejs && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && \ apt-get install -y yarn : Tải xuống và chạy tập lệnh thiết lập NodeSource để cài đặt Node.js. curl -fsSL https://deb.nodesource.com/setup_current.x | bash - : Cài đặt Node.js. apt-get install -y nodejs : Thêm khóa GPG Sợi để xác minh các gói của nó. curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - : Thêm kho lưu trữ của Yarn vào danh sách các nguồn. echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list : Cập nhật danh sách gói và cài đặt Yarn. apt-get update && apt-get install -y yarn 4. Biến môi trường ENV NODE_OPTIONS=--openssl-legacy-provider : Đặt biến môi trường để bật hỗ trợ OpenSSL kế thừa cho Node.js. ENV NODE_OPTIONS=--openssl-legacy-provider 5. Đặt thư mục làm việc WORKDIR /rails : Đặt thư mục làm việc cho các hướng dẫn tiếp theo thành . WORKDIR /rails /rails 6. Xây dựng các đối số và biến môi trường ARG RAILS_ENV ENV RAILS_ENV=$RAILS_ENV : Xác định đối số xây dựng có tên để chỉ định môi trường Rails (như , , ). ARG RAILS_ENV RAILS_ENV development test production : Đặt biến môi trường thành giá trị của đối số bản dựng. ENV RAILS_ENV=$RAILS_ENV RAILS_ENV 7. Cài đặt ứng dụng Gems COPY Gemfile Gemfile.lock ./ RUN bundle install : Sao chép và vào thư mục làm việc. COPY Gemfile Gemfile.lock ./ Gemfile Gemfile.lock : Cài đặt đá quý Ruby được chỉ định trong . RUN bundle install Gemfile 8. Cài đặt phụ thuộc giao diện người dùng COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile : Sao chép và vào thư mục làm việc. COPY package.json yarn.lock ./ package.json yarn.lock : Cài đặt các phần phụ thuộc giao diện người dùng bằng Sợi, đảm bảo nó sử dụng các phiên bản chính xác trong . RUN yarn install --frozen-lockfile yarn.lock 9. Sao chép mã ứng dụng COPY . . : Sao chép tất cả mã ứng dụng vào thư mục làm việc. COPY . . 10. Biên dịch trước mã Bootsnap RUN bundle exec bootsnap precompile --gemfile app/ lib/ : Biên dịch trước bộ đệm Bootsnap để có thời gian khởi động ứng dụng Rails nhanh hơn. Bootsnap là một gem giúp tăng tốc thời gian khởi động Ruby và Rails bằng cách lưu vào bộ nhớ đệm các phép tính đắt tiền. RUN bundle exec bootsnap precompile --gemfile app/ lib/ 11. Biên dịch trước tài sản cho sản xuất RUN if [ "$RAILS_ENV" = "production" ]; then \ SECRET_KEY_BASE=1 bin/rails assets:precompile; \ fi : Chỉ chạy quá trình biên dịch trước nội dung có điều kiện nếu được đặt thành . Bước này rất quan trọng để chuẩn bị tài sản cho môi trường sản xuất. RUN if [ "$RAILS_ENV" = "production" ]; then ... RAILS_ENV production 12. Tập lệnh điểm vào COPY bin/docker-entrypoint /rails/bin/ RUN chmod +x /rails/bin/docker-entrypoint : Sao chép tập lệnh điểm nhập tùy chỉnh vào vùng chứa. COPY bin/docker-entrypoint /rails/bin/ : Làm cho tập lệnh điểm vào có thể thực thi được. RUN chmod +x /rails/bin/docker-entrypoint 13. Xác định điểm vào và lệnh ENTRYPOINT ["/rails/bin/docker-entrypoint"] EXPOSE 5000 // you can use any port of your choice CMD ["./bin/rails", "server"] : Đặt tập lệnh điểm nhập sẽ chạy khi vùng chứa khởi động. Tập lệnh này thường thiết lập môi trường, chuẩn bị cơ sở dữ liệu và khởi động ứng dụng. ENTRYPOINT ["/rails/bin/docker-entrypoint"] : Cho biết container lắng nghe trên cổng 5000. Đây là một tính năng tài liệu và không xuất bản cổng. EXPOSE 5000 : Chỉ định lệnh mặc định sẽ chạy khi container khởi động, tức là khởi động máy chủ Rails. CMD ["./bin/rails", "server"] docker-compose.yml Tệp được sử dụng để xác định và chạy các ứng dụng Docker nhiều vùng chứa. Nó cho phép bạn định cấu hình các dịch vụ, mạng và ổ đĩa của ứng dụng trong một tệp duy nhất. Trong trường hợp này, chúng tôi sẽ sử dụng hai dịch vụ. Đây là tệp cho ứng dụng Rails: docker-compose.yml docker-compose.yml 1. ) Dịch vụ cơ sở dữ liệu ( db codedb: image: postgres:14.2-alpine container_name: demo-postgres-14.2 volumes: - postgres_data:/var/lib/postgresql/data command: "postgres -c 'max_connections=500'" environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - "5432:5432" : Chỉ định hình ảnh Docker để sử dụng cho dịch vụ này. Trong trường hợp này, đó là hình ảnh PostgreSQL 14.2 dựa trên bản phân phối Alpine Linux. Hình ảnh Alpine được biết đến với kích thước nhỏ, có thể giúp giảm kích thước hình ảnh tổng thể. image: postgres:14.2-alpine : Đặt tên cho vùng chứa . Tên này được sử dụng để tham chiếu vùng chứa trong lệnh và nhật ký. container_name: demo-postgres-14.2 demo-postgres-14.2 volumes : Gắn một tập được đặt tên vào bên trong vùng chứa. Thư mục này là nơi PostgreSQL lưu trữ dữ liệu của nó, đảm bảo rằng dữ liệu cơ sở dữ liệu vẫn tồn tại giữa các lần khởi động lại vùng chứa. postgres_data:/var/lib/postgresql/data: postgres_data /var/lib/postgresql/data : Ghi đè lệnh mặc định của hình ảnh PostgreSQL. Nó khởi động PostgreSQL với tùy chọn cấu hình để tăng số lượng kết nối tối đa lên 500. command: "postgres -c 'max_connections=500'" environment : : Đặt tên của cơ sở dữ liệu mặc định để tạo, sử dụng biến môi trường . POSTGRES_DB: ${POSTGRES_DB} POSTGRES_DB : Đặt tên người dùng mặc định để truy cập cơ sở dữ liệu PostgreSQL, sử dụng biến môi trường . POSTGRES_USER: ${POSTGRES_USER} POSTGRES_USER : Đặt mật khẩu cho người dùng mặc định, sử dụng biến môi trường . POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_PASSWORD ports : : Ánh xạ cổng 5432 trên máy chủ tới cổng 5432 trong vùng chứa. Điều này cho phép truy cập vào PostgreSQL trên máy chủ qua cổng 5432. "5432:5432" 2. ) Dịch vụ ứng dụng web ( demo-web codedemo-web: build: context: . args: - RAILS_ENV=${RAILS_ENV} command: "./bin/rails server -b 0.0.0.0" environment: - RAILS_ENV=${RAILS_ENV} - POSTGRES_HOST=${POSTGRES_HOST} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - RAILS_MASTER_KEY=${RAILS_MASTER_KEY} volumes: - .:/rails - app-storage:/rails/storage depends_on: - db ports: - "3000:3000" build: : Chỉ định bối cảnh xây dựng cho hình ảnh Docker. Trong trường hợp này, đề cập đến thư mục hiện tại. Điều này có nghĩa là Docker sẽ sử dụng Dockerfile trong thư mục hiện tại để xây dựng image. context: . . args : : Truyền đối số xây dựng cho quy trình xây dựng Docker, cho phép bạn chỉ định môi trường Rails (như , hoặc ). RAILS_ENV=${RAILS_ENV} RAILS_ENV development test production : Ghi đè lệnh mặc định của hình ảnh Docker. Khởi động máy chủ Rails và liên kết nó với tất cả các giao diện mạng ( ), điều này cần thiết để dịch vụ có thể truy cập được từ bên ngoài vùng chứa. command: "./bin/rails server -b 0.0.0.0" 0.0.0.0 environment: : Đặt môi trường Rails bên trong vùng chứa bằng biến môi trường . RAILS_ENV=${RAILS_ENV} RAILS_ENV : Đặt địa chỉ máy chủ PostgreSQL. POSTGRES_HOST=${POSTGRES_HOST} : Đặt tên cơ sở dữ liệu. POSTGRES_DB=${POSTGRES_DB} : Đặt người dùng PostgreSQL. POSTGRES_USER=${POSTGRES_USER} : Đặt mật khẩu người dùng PostgreSQL. POSTGRES_PASSWORD=${POSTGRES_PASSWORD} : Đặt khóa chính Rails, được sử dụng để mã hóa thông tin xác thực và các bí mật khác. RAILS_MASTER_KEY=${RAILS_MASTER_KEY} volumes : : Gắn thư mục hiện tại (nơi chứa tệp ) vào bên trong vùng chứa. Điều này cho phép bạn chỉnh sửa các tệp trên máy chủ của mình và phản ánh những thay đổi đó bên trong vùng chứa. .:/rails docker-compose.yml /rails : Gắn một khối lượng được đặt tên vào bên trong vùng chứa. Điều này thường được sử dụng để lưu trữ các tệp dành riêng cho Rails như nhật ký, tải lên và tệp được lưu trong bộ nhớ cache. app-storage:/rails/storage app-storage /rails/storage depends_on : : Đảm bảo rằng dịch vụ đợi dịch vụ sẵn sàng trước khi bắt đầu. Docker Compose xử lý thứ tự bắt đầu dịch vụ dựa trên cài đặt này. db demo-web db ports: : Ánh xạ cổng 3000 trên máy chủ tới cổng 3000 trong vùng chứa. Điều này cho phép bạn truy cập ứng dụng Rails trên máy chủ qua cổng 3000. "3000:3000" Tập codevolumes: postgres_data: app-storage: : Xác định một tập được đặt tên được dịch vụ sử dụng để duy trì dữ liệu PostgreSQL. postgres_data postgres_data db : Xác định khối lượng được đặt tên được sử dụng bởi dịch vụ để duy trì dữ liệu dành riêng cho ứng dụng, chẳng hạn như nội dung tải lên và nhật ký. app-storage app-storage demo-web bin/docker-entrypoint Tập lệnh là một phần quan trọng trong quá trình thiết lập Docker. Nó được thực thi khi vùng chứa khởi động và thường xử lý việc thiết lập môi trường, chuẩn bị cơ sở dữ liệu và các tác vụ khởi tạo khác cần thiết trước khi khởi động ứng dụng chính. Dưới đây là ví dụ về tập lệnh và giải thích chi tiết về từng phần: bin/docker-entrypoint bin/docker-entrypoint Shebang và thoát khi có lỗi bashCopy code#!/bin/bash set -e : Dòng này chỉ định rằng tập lệnh sẽ được chạy bằng shell Bash. #!/bin/bash : Điều này hướng dẫn tập lệnh thoát ngay lập tức nếu bất kỳ lệnh nào trả về mã thoát khác 0. Điều này giúp đảm bảo rằng nếu bất kỳ bước nào không thành công, tập lệnh sẽ dừng thực thi, điều này có thể ngăn các bước tiếp theo chạy ở trạng thái không hợp lệ. set -e Tạo hoặc di chuyển cơ sở dữ liệu có điều kiện # If running the rails server then create or migrate existing database if [ "${*}" == "./bin/rails server" ]; then ./bin/rails db:create ./bin/rails db:prepare fi : Câu lệnh điều kiện này kiểm tra xem lệnh được truyền tới tập lệnh ( ) có phải là hay không. là một tham số đặc biệt chứa tất cả các tham số vị trí được truyền cho tập lệnh. if [ "${*}" == "./bin/rails server" ]; then ... fi "${*}" ./bin/rails server * ./bin/rails db : Nếu điều kiện được đáp ứng, lệnh này sẽ cố gắng tạo cơ sở dữ liệu. Nó tương đương với việc chạy để thiết lập cơ sở dữ liệu như được xác định trong tệp cấu hình cơ sở dữ liệu ( ). rails db:create config/database.yml ./bin/rails db : Lệnh này sẽ chạy để đảm bảo cơ sở dữ liệu được thiết lập và di chuyển. Nó sẽ tạo cơ sở dữ liệu nếu nó không tồn tại và chạy di chuyển nếu cơ sở dữ liệu đã được tạo. Đây là sự kết hợp của và . rails db:prepare rails db:create rails db:migrate Thực hiện quy trình chính bashCopy codeexec "${@}" : Điều này thay thế quy trình shell hiện tại bằng lệnh được truyền dưới dạng đối số cho tập lệnh. Biểu tượng chứa tất cả các tham số vị trí được truyền cho tập lệnh. Ví dụ: nếu tập lệnh được gọi với , dòng này sẽ chạy một cách hiệu quả như quy trình chính của vùng chứa. exec "${@}" @ ./bin/rails server ./bin/rails server Phần kết luận được thiết kế tốt là điều cần thiết để tạo ra một môi trường nhất quán và đáng tin cậy cho ứng dụng Ruby on Rails và React của bạn. Bằng cách xác định hình ảnh cơ sở, đặt biến môi trường và cài đặt các phần phụ thuộc, bạn đảm bảo rằng ứng dụng của mình chạy trơn tru trên nhiều môi trường khác nhau. Dockerfile Docker không chỉ hợp lý hóa quy trình phát triển của bạn mà còn nâng cao độ tin cậy của ứng dụng trong quá trình sản xuất. Có những lĩnh vực tối ưu hóa, nhưng đây chỉ là tổng quan chung về cách neo ứng dụng Rails. Tập lệnh đầy đủ cho kết quả, và Dockerfile docker-compose.yml bin/docker-entrypoint ARG RUBY_VERSION=3.1.4 FROM ruby:$RUBY_VERSION # Install dependencies RUN apt-get update -qq && \ apt-get install -y build-essential libvips bash bash-completion libffi-dev tzdata postgresql curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man # Install Node.js and Yarn RUN curl -fsSL https://deb.nodesource.com/setup_current.x | bash - && \ apt-get install -y nodejs && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && \ apt-get install -y yarn # Set environment variable to enable legacy OpenSSL support ENV NODE_OPTIONS=--openssl-legacy-provider # Rails app lives here WORKDIR /rails # Set environment variable for the build ARG RAILS_ENV ENV RAILS_ENV=$RAILS_ENV # Install application gems COPY Gemfile Gemfile.lock ./ RUN bundle install # Install frontend dependencies COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile # Copy application code COPY . . # Precompile bootsnap code for faster boot times RUN bundle exec bootsnap precompile --gemfile app/ lib/ # Precompiling assets for production without requiring secret RAILS_MASTER_KEY RUN if [ "$RAILS_ENV" = "production" ]; then \ SECRET_KEY_BASE=1 bin/rails assets:precompile; \ fi # Entrypoint prepares the database. COPY bin/docker-entrypoint /rails/bin/ RUN chmod +x /rails/bin/docker-entrypoint # Use an absolute path for the entry point script ENTRYPOINT ["/rails/bin/docker-entrypoint"] # Start the server by default, this can be overwritten at runtime EXPOSE 5000 CMD ["./bin/rails", "server"] services: db: image: postgres:14.2-alpine container_name: demo-postgres-14.2 volumes: - postgres_data:/var/lib/postgresql/data command: "postgres -c 'max_connections=500'" environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - "5432:5432" demo-web: build: context: . args: - RAILS_ENV=${RAILS_ENV} command: "./bin/rails server -b 0.0.0.0" environment: - RAILS_ENV=${RAILS_ENV} - POSTGRES_HOST=${POSTGRES_HOST} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - RAILS_MASTER_KEY=${RAILS_MASTER_KEY} volumes: - .:/rails - app-storage:/rails/storage depends_on: - db ports: - "3000:3000" volumes: postgres_data: app-storage: #!/bin/bash set -e # If running the rails server then create or migrate existing database if [ "${*}" == "./bin/rails server" ]; then ./bin/rails db:create ./bin/rails db:prepare fi exec "${@}"