0

I use docker-compose for running my containers in docker. I have two services - one of celerybeat and other the web (I have many others but considering only these services because they contain my problem).

docker-compose.yml file looks like this:

.
.
.

celerybeat:
  image: web-image
  volumes:
    - /home/ubuntu/celerybeat:/code/celerybeat
  command: >
    /bin/ash -c "su -m celery -c 'celery -A <application_here> beat -s /code/celerybeat/celerybeat-schedule'"

web:
  image: web-image
  volumes:
    - /home/ubuntu/celerybeat:/code/celerybeat
  command: >      
    <some_command_to_run_server>

In my Dockerfile I have added these commands for proper permissions

RUN mkdir celerybeat
RUN touch celerybeat/celerybeat-schedule
RUN chown -R celery:celery celerybeat

Note: In my compose file structure written above I have provided volume mounts for both containers (but actually I am using one at a time), for the ease of not writing the compose files again and again.

The problem is actually here only. Technically the volume mount should be provided only in the celerybeat service. When I write volume mount for celerybeat-schedule in the celerybeat docker service I get permission denied. Whereas when I write the volume mount command in the web service celerybeat service starts happily. What is happening here can anyone explain me? I need a fix for this.

Arpit Goyal
  • 2,212
  • 11
  • 31
  • When you say you write the volume mount command in the web service celerybeat service and it starts happily, what command are you running exactly? – bluescores Dec 18 '17 at 13:07
  • I fixed the issue although I still can't understand this. The issue was that I was running the command for starting the beat service as a celery user. But when I started the service without adding the `su -m celery -c` bit, it worked. Why is this issue arising? – Arpit Goyal Dec 18 '17 at 13:07

2 Answers2

2

The issue you have is below

volumes:
    - /home/ubuntu/celerybeat:/code/celerybeat

By doing the above volume mapping, you effectively cancel the below

RUN chown -R celery:celery celerybeat

And inherit the permissions from the volume mount. The fix is either not to use the celery user or use below in your yaml

command: >
  /bin/ash -c "chown -R celery:celery /code/celerybeat && su -m celery -c 'celery -A <application_here> beat -s /code/celerybeat/celerybeat-schedule'"
Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
1

Order of operations - docker build then docker run (with docker-compose up counting as a docker run.

When you mount a volume, the files and folders in that volume are owned by root. Having RUN chown -R celery:celery celerybeat would work if you didn't mount a volume. When you bind mount the volume in your docker run/docker-compose up, anything that exists at /code/celerybeat is overwritten, including permissions.

So when you run celerybeat as root, you're good in this case. If you run it as the celery user as you have tried, that user can't access /code/celerybeat because as a bind mount volume, it's owned by root.

Instead of chowning the directory in your Dockerfile, run chown as part of an entrypoint script. Something like:

#!/bin/bash

chown -R celery:celery celerybeat
/bin/ash -c "su -m celery -c 'celery -A <application_here> beat -s /code/celerybeat/celerybeat-schedule'"

This script, and thus chown, execute after the bind mount, where RUN chown -R celery:celery celerybeat executes before the bind mount, and is overwritten by it.

bluescores
  • 4,437
  • 1
  • 20
  • 34