I have a Ruby on Rails container with Sidekiq in it.
I have a schedule/cron job in the application. As We know, schedule jobs are registered when the application boots.
If I assume that there will be many users one day and I will create multiple container instances for the application, will this cause Sidekiq to execute on multiple containers?
If the answer is yes (execute multiple jobs in each container), how do I make this job only executed by one container?
version: '3.8'
services:
thedatabase:
image: postgres:12
volumes:
- ./database:/var/lib/postgresql/data
environment:
POSTGRES_USER: theuser
POSTGRES_PASSWORD: thepass
ports:
- '5432:5432'
networks:
- excnetwork
theapi:
build:
context: ./dex-api
dockerfile: Dockerfile
volumes:
- ./dex-api:/web
env_file:
- ./dex-api/.env
ports:
- "8081:3000"
depends_on:
- thedatabase
networks:
- excnetwork
redis:
image: redis
command: 'redis-server --requirepass "yourpassword"'
volumes:
- ./redis:/var/lib/redis/data
ports:
- '6379:6379'
networks:
- excnetwork
volumes:
database:
dex-api:
redis:
networks:
excnetwork:
driver: bridge
CodePudding user response:
[If I] create multiple container instances for the application, will this cause Sidekiq to execute on multiple containers?
Yes; but Sidekiq is clever enough to only run each job once, even if there are multiple workers. Similarly, if you're using the paid version of Sidekiq and its periodic jobs, they shouldn't be duplicated since "the leader process enqueues cron jobs" (doc link).
You don't describe how you're starting Rails and Sidekiq, but your Compose setup only has one application container. You might find it useful to split these into two, which will make it easier to scale the components and protect the Web application if a scheduled job has a problem. In your Dockerfile, start one or the other (I'd default to the Rails server)
ENTRYPOINT ["bundle", "exec"]
CMD ["rails", "server", "-b", "0.0.0.0", "-p", "3000"]
In your Compose file you can start multiple containers from the same image, overriding the command:
in some of them if required.
services:
theapi:
build: ./dex-api
env_file:
- ./dex-api/.env
ports:
- "8081:3000"
depends_on:
- thedatabase
- redis
theworker:
build: ./dex-api # <-- same as `theapi`
command: sidekiq # <-- override Dockerfile `CMD`
env_file:
- ./dex-api/.env
depends_on:
- thedatabase
- redis
CodePudding user response:
Whilst there's no single answer that solves it all you can use tried and tested means. One of them is to put Sidekiq in a sidecar. You definitely need Sidekiq to be run as a single, independent instance.
There are other patterns for a multi-container solution such as ambassador and adapter but, a sidecar seems to be the most appropriate option in this instance.
Read more here: