我正在将一个 Rails 应用程序从 Heroku 移动到 Linux 服务器并使用 Caprover 进行部署。这是一个非常依赖后台作业的应用程序,我使用 sidekiq 运行它。
我成功地通过在 Dockerfile 的 CMD 中启动的脚本运行 Rails 服务器 (
bundle exec rails server -b 0.0.0.0 -p80 &
) 和 sidekiq (bundle exec sidekiq &
),使其正常工作。
但我想如果 Rails 服务器位于一个 Docker 容器中而 sidekiq 位于另一个容器中,情况会好得多(关注点分离)。但我不知道如何连接它们。如何告诉我的 Rails 应用 sidekiq 位于另一个容器中?
因为我使用 Caprover,所以我只能使用 Dockerfiles 来部署我的映像,所以 我无法使用 docker-compose。
有没有办法告诉rails它应该使用在某个Docker容器中找到的某个sidekiq?如果有任何帮助,Caprover 使用 Docker swarm。
我是否以错误的方式思考这个问题?
目前我的设置如下:
我想要的设置是:
以我目前的限制,这可能吗?
我的rails + sidekiq Dockerfile如下:
FROM ruby:2.6.4-alpine
#
RUN apk update && apk add nodejs yarn postgresql-client postgresql-dev tzdata build-base ffmpeg
RUN apk add --no-cache --upgrade bash
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install --deployment --without development test
COPY . /myapp
RUN yarn
RUN bundle exec rake yarn:install
# Set production environment
ENV RAILS_ENV production
ENV RAILS_SERVE_STATIC_FILES true
# Assets, to fix missing secret key issue during building
RUN SECRET_KEY_BASE=dumb bundle exec rails assets:precompile
# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 80
COPY start_rails_and_sidekiq.sh /myapp/start_rails_and_sidekiq.sh
RUN chmod +x /myapp/start_rails_and_sidekiq.sh
# Start the main process.
WORKDIR /myapp
CMD ./start_rails_and_sidekiq.sh
start_rails_and_sidekiq.sh
看起来像这样:
#!/bin/bash
# Start the first process
bundle exec rails server -b 0.0.0.0 -p80 &
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start Rails server: $status"
exit $status
fi
# Start the second process
bundle exec sidekiq &
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start Sidekiq: $status"
exit $status
fi
# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container exits with an error
# if it detects that either of the processes has exited.
# Otherwise it loops forever, waking up every 60 seconds
while sleep 60; do
ps aux |grep puma |grep -q -v grep
PROCESS_1_STATUS=$?
ps aux |grep sidekiq |grep -q -v grep
PROCESS_2_STATUS=$?
# If the greps above find anything, they exit with 0 status
# If they are not both 0, then something is wrong
if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
echo "One of the processes has already exited."
exit 1
fi
done
我彻底迷路了! 预先感谢!
根据CapRover docs,似乎可以在CapRover上运行Docker Compose,但我自己还没有尝试过。
尽管此 CapRover 示例适用于不同的 Web 应用程序,但内部访问原理是相同的:
如果您想从其他容器访问它,只需在容器名称中添加 srv-captain-- 前缀即可。
但是,这个方法不是告诉 Rails Web 应用程序在哪里找到 PostgreSQL DB 容器的吗?还是通过外部子域名访问?
这篇文章已经有 3 年历史了,但没有答案,我在railway.app 上运行应用程序时遇到了同样的问题,其中不支持 Docker Compose。我没有创建另一个容器,而是在 foreman gem 的帮助下使用 Procfile 来启动这两个服务:
在您的 Dockerfile 中: 添加
RUN gem install foreman
最后将CMD更改为CMD ["foreman", "start"]
在项目根目录添加Procfile:
web: bin/rails server -b 0.0.0.0 -p 80
worker: bundle exec sidekiq
这将同时启动,并且还会为您提供漂亮且有用的日志文件。