Nhật ký công việc cho nhiệm vụ "Triển khai cục bộ trang web Ruby ban đầu"
Làm rõ về tính khả tái lập khi chạy Docker
Khi khởi động lại container, một sự cố điển hình của các ứng dụng Rails cũ (legacy) đã được phát hiện: ứng dụng ghi các tệp runtime trực tiếp vào cây thư mục dự án, vốn được gắn kết (bind-mount) toàn bộ vào container.
Lỗi được phát hiện
Rails từ chối khởi động với thông báo A server is already running vì tệp server.pid vẫn còn tồn tại trong tmp/pids/ từ lần chạy trước. Khi dừng đột ngột hoặc tạo lại container, tệp này vẫn nằm trên hệ thống tệp của host cùng với dự án.
Nguyên nhân
Toàn bộ thư mục trang web được mount vào container. Điều này tạo ra đồng thời hai hiệu ứng:
- Nội dung được chuẩn bị trong image bên trong thư mục ứng dụng có thể bị ghi đè bởi nội dung bind-mount của host sau khi container khởi động. Do đó, việc cài đặt các phụ thuộc gắn liền với trạng thái của dự án được mount không thể được coi là hoàn tất một cách đáng tin cậy chỉ ở giai đoạn build Dockerfile.
- Các tệp runtime của Rails (
tmp/pidsvà có thể là dữ liệu tạm thời khác) được lưu bên trong thư mục được mount và tồn tại lâu hơn vòng đời của container. Tệp PID cũ sau đó sẽ chặn lần khởi động mới.
Giải pháp đã áp dụng
Lệnh khởi động dịch vụ đã được bổ sung thêm một bước chuẩn bị:
rm -rf /app/tmp/pids/ && (bundle check || bundle install --frozen) && bundle exec rails server -b 0.0.0.0
Logic khởi động hiện tại như sau:
- các tệp PID cũ của Rails bị xóa trước khi khởi động;
bundle checknhanh chóng kiểm tra sự hiện diện của các gem cần thiết;bundle install --frozenchỉ được thực thi nếu các phụ thuộc còn thiếu hoặc chưa đầy đủ;- sau khi chuẩn bị xong, Rails server được khởi chạy, lắng nghe trên giao diện của container.
Kết luận kiến trúc
Mô hình Docker hiện tại được định hướng để tái tạo trực tiếp nhất có thể một dự án legacy thông qua bind-mount mã nguồn, thay vì sử dụng một image hoàn toàn bất biến (immutable). Đối với môi trường di chuyển thử nghiệm, điều này có thể chấp nhận được, nhưng điều quan trọng cần lưu ý là trạng thái của dự án và container runtime bị trộn lẫn một phần.
Khi tiếp tục sử dụng môi trường này, cần quản lý riêng các thư mục tmp, log, các tệp tải lên và các phụ thuộc để các tệp tạm thời của ứng dụng legacy không ảnh hưởng đến tính lặp lại khi khởi động. Nếu môi trường cần được sử dụng lâu dài hoặc bàn giao cho các nhà phát triển khác, việc tách các thư mục runtime có thể thay đổi thành các volume riêng biệt hoặc loại khỏi cơ chế bind-mount là điều hợp lý.
Kết quả
Sau khi sửa đổi lệnh khởi động, container có thể sống sót qua các lần khởi động lại một cách chính xác và tự động khôi phục các phụ thuộc bị thiếu mà không cần xóa thủ công các tệp PID của Rails.
Nhiệm vụ: Triển khai cục bộ trang web Ruby ban đầu
Thiết lập bản sao cục bộ có thể tái tạo của dự án Ruby hiện tại để phân tích, di chuyển và kiểm tra hành vi của trang web cũ.