docker icon indicating copy to clipboard operation
docker copied to clipboard

Background jobs: Cron does not run

Open beryl03 opened this issue 3 years ago • 33 comments

Tag: latest (2022/02/04) When trying to setup Cron as the background job, it seems it cannot work without a lot of work on top of the image Missing: Packages: Cron (and dependencies) Service: Something to run Crontab jobs Settings to Reproduce:

  1. Install docker image from tag: latest
  2. Setup dependencies (SQL DB) and config to get NextCloud started
  3. Enable Cron background Job
  • Settings -> Basic Settings -> Select " Cron" Radio Button under "Background jobs" section
  1. Wait 5 minutes and reload page
  • observe that the last job was run over 5 minutes ago (PROBLEM)
  1. Log into docker container terminal as Root
  2. Install Cron package and dependencies
  3. Install editor and configure EDITOR env var (I used nano)
  4. edit crontab (crontab -u www-data -e) to add recommended line per documentation (https://docs.nextcloud.com/server/23/admin_manual/configuration_server/background_jobs_configuration.html)
  5. Wait 5 minutes and reload page
  • observe that the last job was run over 5 minutes ago (PROBLEM)
  1. Further investigation you can see that there are no Cron logs at expected locations, which indicates Cron is not even running. I was unable to figure out how to start the Cron service since the docker image is stripped down version of Debian. SystemD does not seem to be installed.

Mitigation: Mitigation is to setup Cron on Host and run "docker exec -u 33 -t nextcloud-app php -f /var/www/html/cron.php" (www-data UID = 33)

  • Note: on Fedora Server, Cron is not enabled/running after Cron is installed. the service has to be enabled for Cron jobs to run (systemctl enable crond.service). I assume something similar needs to be done within the docker image/container.

Proposed Solution:

  1. Create Docker Image with cron installed and setup such that selecting Cron as a background job is enough to setup the cron job. OR
  2. Update Documentation to note that official docker image[s] do not support Cron Jobs in a Docker Container and list links to solutions or mitigations.

beryl03 avatar Feb 15 '22 18:02 beryl03

Here is some info from docker image inspect for image versioning information:

"Id": "sha256:df82fda354851c092a2e95bb49189231931c357c36ab03a4ec3c19fdd64c4925",
"RepoTags": [
"nextcloud:latest"
],
"RepoDigests": [
"nextcloud@sha256:867d3f34d5a7baa1fb48b18b86e36486e406832881219c5bcd7f9952bc947366"
],

beryl03 avatar Feb 15 '22 18:02 beryl03

The background cron should be run in a separate container If you provide the docker-compose.yml you using I can help you with how to set up the cron container. Or the docker compose examples right here can help you. https://github.com/nextcloud/docker/blob/master/.examples/docker-compose/insecure/mariadb/apache/docker-compose.yml It should be like that

app:
  image: nextcloud:apache
  restart: always
  ports:
    - 127.0.0.1:8080:80
  volumes:
    - nextcloud:/var/www/html
  environment:
    - MYSQL_HOST=db
    - REDIS_HOST=redis
  env_file:
    - db.env
  depends_on:
    - db
    - redis

cron:
  image: nextcloud:apache
  restart: always
  volumes:
    - nextcloud:/var/www/html
  entrypoint: /cron.sh
  depends_on:
    - db
    - redis

Karem-sobhy avatar Feb 17 '22 05:02 Karem-sobhy

That could work but if it is starting a while new container, that sounds like a bit more RAM just to run Cron.php. also seeing two containers sharing the volume seems odd. Since you could have file IO errors. If this is the recommended way, there was no mention of this method in any of the documentation (docs.nextcloud.com).

beryl03 avatar Feb 17 '22 14:02 beryl03

so few ways to use the cron is,

  • use separate compose like above
  • use host cron and docker exec command
  • custom image to run cron apa apache in parallel

martadinata666 avatar Feb 17 '22 14:02 martadinata666

That could work but if it is starting a while new container, that sounds like a bit more RAM just to run Cron.php. also seeing two containers sharing the volume seems odd. Since you could have file IO errors. If this is the recommended way, there was no mention of this method in any of the documentation (docs.nextcloud.com).

That's the recommended way in the examples and no proplem with sharing the same volume because it's only calls the cron file and about ram it uses 38mb of ram so not really a problem so don't worry and spin that extra cron container

Edit.. You don't need to add all volumes only the /var/www/html

Karem-sobhy avatar Feb 17 '22 16:02 Karem-sobhy

@martadinata666 , I use the host to push a docker exec, and it works, and cron initiates sending the command to the container. With regards to all options, I did not find any documentation stating the docker image crontab does not work and steps to take to fix it. I think it would be easiest to add notes to the documentation to state such and list solutions and links. Documentation locations I am referring to: https://github.com/nextcloud/docker/wiki https://docs.nextcloud.com/server/23/admin_manual/configuration_server/background_jobs_configuration.html

beryl03 avatar Feb 17 '22 18:02 beryl03

@martadinata666 , I use the host to push a docker exec, and it works, and cron initiates sending the command to the container. With regards to all options, I did not find any documentation stating the docker image crontab does not work and steps to take to fix it. I think it would be easiest to add notes to the documentation to state such and list solutions and links. Documentation locations I am referring to: https://github.com/nextcloud/docker/wiki https://docs.nextcloud.com/server/23/admin_manual/configuration_server/background_jobs_configuration.html

But it's documented in the official examples here https://github.com/nextcloud/docker/blob/master/.examples/docker-compose/insecure/mariadb/apache/docker-compose.yml

Karem-sobhy avatar Feb 17 '22 19:02 Karem-sobhy

@kemoantemo , I am not saying what you linked is bad. I am saying me as a user never found that in all the searching I did. What good is "documentation" if a user cannot find the "documentation" to find the answer? What I am asking is if we can help users (like me) find the information we need by putting the documentation or links to documentation where a [new] user would look.

beryl03 avatar Feb 17 '22 20:02 beryl03

I get you but any new user should follow the examples of the official docker so where is the problem? Maybe it's not in the documentation of nextcloud because next cloud have a lot of deploy methods so you should check the examples of the method you going to use and don't worry from the cron container it's not fully nextcloud container it doesn't run nextcloud instance it just run a cron process that calls cron.php every 5 minutes so it's pretty good and easy to applicate solution. you can use the supervisored to run nextcloud and cron from same container but it's really almost the same because after all it's the same PID so just use the official examples and don't worry

Karem-sobhy avatar Feb 17 '22 20:02 Karem-sobhy

everyone got personal preferences, in my case i rather not modify host so i create custom image with added supervisor to run cron and apache in parallel. Because i also need additional job like full text search, and preview generator, and pretty messed up on upgrade as it get overwritten cmiiw

martadinata666 avatar Feb 18 '22 01:02 martadinata666

The NC docker docs just mention cron briefly, pointing to the examples:

The examples folder gives a few examples on how to add certain functionalities, like including the cron job, smb-support or imap-authentication.

Here is where cron is defined in the examples

This would be the correct way to do it with docker-compose*. Containers should be a single process to allow logs and error handling to make sense.

Since almost every(?) instance needs cron, maybe it should be more prominent in the docs?

*(In Kubernetes you can use a CronJob to handle the cron script which feels somewhat nicer.)

especially-relative avatar Feb 19 '22 18:02 especially-relative

Sorry to revive this a month later, but I am also facing issues with my Cron set-up.

My docker-compose.yml
version: '2'

services:
  db:
    image: mariadb:10.5
    restart: always
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    volumes:
      - ./db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=[pw]
      - MYSQL_PASSWORD=[pw]
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud

  redis:
    image: redis:alpine
    restart: always

  app:
    image: nextcloud
    restart: always
    ports:
      - 80:80
    depends_on:
      - db
    links:
      - redis
    volumes:
      - ./config:/var/www/html/config
      - ./apps:/var/www/html/custom_apps
      - /nextcloud-data:/var/www/html/data
    environment:
      - MYSQL_PASSWORD=[pw]
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=db
      - SMTP_HOST=mail.me.eu
      - SMTP_SECURE=tls
      - SMTP_PORT=587
      - [email protected]
      - SMTP_PASSWORD=[pw]
      - MAIL_DOMAIN=me.eu
      - MAIL_FROM_ADDRESS=system
      - TRUSTED_PROXIES=192.xxx.xxx.xx
      - TRUSTED_DOMAIN=cloud.me.eu
      - REDIS_HOST=redis

  cron:
    image: nextcloud
    restart: always
    volumes:
      - ./config:/var/www/html/config
      - ./apps:/var/www/html/custom_apps
      - /nextcloud-data:/var/www/html/data
    entrypoint: /cron.sh
    depends_on:
      - db
      - redis

Despite copying the proposed cron container description - except the volumes as I'm only using more specific ones rather than just the generic /var/www/html. However, docker doesn't seem to do anything. I am still seeing the notification in Nextcloud admin pages that the 'last executed job was yesterday'.

I asked support on the forum but unfortunately the answers provided there don't really get me much further. On the one hand I'm hoping to get feedback on my situation. On the other hand I'm here to support the call for more documentation/explanation on using docker (more than only an example file that doesn't explain anything and isn't of much help when debugging).

keunes avatar Mar 22 '22 22:03 keunes

@keunes the /var/www/html is an essential for not just cron but also for upgrading you should have it first then take every custom data or config as you want after so try to make a volume for /var/www/html If you need help you can email me at [email protected] I'd love to help

Karem-sobhy avatar Mar 22 '22 23:03 Karem-sobhy

@keunes try setting the MYSQL variables in the environment of the cron container as well. They're not specifying any in the example, but I am going to guess that is because they are using defaults.

especially-relative avatar Mar 23 '22 00:03 especially-relative

@danieljkemp it's getting it from the config file no need to he just need to mount the /var/www/html

Karem-sobhy avatar Mar 23 '22 00:03 Karem-sobhy

@keunes the /var/www/html is an essential for not just cron but also for upgrading you should have it first then take every custom data or config as you want after so try to make a volume for /var/www/html

You're amazing, this worked! Just for my understanding: why is it that adding this 'parent' volume fixed it? Which directories/files are there that cron needs (or that the app needs to know that cron is running)?

I think it would be helpful to mention in the docs (docker Readme) what you told me also, namely that the parent folder must be there, and that child directories may be specified after. I see now that it is mentioned Persistent data somewhat implicitly, but not mentioned in the Docker compose section. I'll prepare a PR with some suggested changes later on.

Also, another question for my understanding: what happens behind the scenes when mounting a parent and then some child directories? On the first run with the global/first volume (when the nextcloud volume doesn't exist yet), does it work like this?

  • first main volume created (replicating the files & structure from the image in the virtual file system), after which
  • any other volume I defined is mounted in the 'parent'/first volume (for which I suppose the original files that were taken from the image are removed first)

keunes avatar Mar 23 '22 07:03 keunes

The essential thing is the /var/www/html in your cron and app need to be inline, if it run separately, the data generated from cron won't available / written to /var/www/html in app. Dunno exactly what is it written or read, /var/www/html/cron.php if you love investigate further.

Assume you had /var/www/html called it base and you also had /var/www/html/config defined called override, both had /var/www/html/config. Container will read from the override not from the base.

martadinata666 avatar Mar 23 '22 08:03 martadinata666

The crazy part is that /var/www/html/ contains the php source of the app. It is actually copying the application source to a volume when the main container updates, then keeping it a volume.

You'd expect to just need to mount the config and data directories into the app containers (main and cron included), and this is indeed how other applications work, but no, the the nextcloud containers references that volume (the one containing just copied source) directly.

especially-relative avatar Mar 23 '22 13:03 especially-relative

@keunes the /var/www/html is an essential for not just cron but also for upgrading you should have it first then take every custom data or config as you want after so try to make a volume for /var/www/html

You're amazing, this worked! Just for my understanding: why is it that adding this 'parent' volume fixed it? Which directories/files are there that cron needs (or that the app needs to know that cron is running)?

I think it would be helpful to mention in the docs (docker Readme) what you told me also, namely that the parent folder must be there, and that child directories may be specified after. I see now that it is mentioned Persistent data somewhat implicitly, but not mentioned in the Docker compose section. I'll prepare a PR with some suggested changes later on.

Also, another question for my understanding: what happens behind the scenes when mounting a parent and then some child directories? On the first run with the global/first volume (when the nextcloud volume doesn't exist yet), does it work like this?

  • first main volume created (replicating the files & structure from the image in the virtual file system), after which
  • any other volume I defined is mounted in the 'parent'/first volume (for which I suppose the original files that were taken from the image are removed first)

The reason that cron didn't work is that the /var/www/html is just empty because you didn't call the entrypoint.sh which checks the version of your nextcloud and if it's existing or not then copy from /usr/src/nextcloud as i remember not sure. So that does happen only if you started the entrypoint.sh so that you don't have problems with the app container but it's surely slow at starting because it copies everytime it starts and for the cron container it doesn't find the php source of nextcloud at /var/www/html so it can't run. I hope I managed to describe it in a good way.

Karem-sobhy avatar Mar 23 '22 17:03 Karem-sobhy

Thanks all for the help and explanations (and sorry for replying only now). I managed to get it working! I think indeed the trick was to add the volume nextcloud:/var/www/html both to app and cron.

keunes avatar Apr 09 '22 14:04 keunes

@danieljkemp it's getting it from the config file no need to he just need to mount the /var/www/html

Thanks for that info, it answered my question, hope it helps someone else too. Quesion: since the config file needs to be retrieved from /var/www/html, why don't we just make the cron service's depends_on parameter to be on app instead of db & redis ? Sounds this could be a good Pull Request?

I feel, from the current example, if it only depends on DB, then we gotta give it all the environment parameters! Which is not really great thing to do.

ninadpchaudhari avatar May 09 '22 04:05 ninadpchaudhari

Quesion: since the config file needs to be retrieved from /var/www/html, why don't we just make the cron service's depends_on parameter to be on app instead of db & redis ? Sounds this could be a good Pull Request?

depends_on only makes the containers start after the dependency containers start what you want is

volumes_from:
     - app

and I did a pull request #1710 for it but it doesn't work with stack so they didn't implement it

Karem-sobhy avatar May 09 '22 07:05 Karem-sobhy

Hello to all, I've the same problems, but adding the nextcloud:apache to my docker-compose.yml did not solve the problem! I've a Synology DS 220+ and installed portainer to do all the docker installations. In this installation I've to adapt the volume part to the right path of my synology. But I think this is the only modifcation. Nextcloud is working for a few weeks, but I've always the error message with cron, so I try to fix this...

Here is my portainer stack (I think it's nearly the same as the docker-compose.yml):

`services: db: image: mariadb:latest container_name: mariadb restart: always ports: - 3306:3306 command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-file-per-table=1 --skip-innodb-read-only-compressed volumes: - /volume1/docker/nextcloud_db:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - MYSQL_PASSWORD=${MYSQL_PASSWORD} - MYSQL_DATABASE=${MYSQL_DATABASE} - MYSQL_USER=${MYSQL_USER} - TZ=Europe/Berlin networks: - web

redis: image: redis:latest restart: always networks: - web volumes: - /volume1/docker/redis:/var/lib/redis

app: image: nextcloud:latest container_name: nextcloud restart: always links: - db volumes: - /volume1/docker/nextcloud:/var/www/html - /volume1/docker/configfiles/nextcloud/.htaccess:/var/www/html/.htaccess logging: driver: "json-file" options: max-size: 10m max-file: "3" environment: - MYSQL_PASSWORD=${MYSQL_PASSWORD} - MYSQL_DATABASE=${MYSQL_DATABASE} - MYSQL_USER=${MYSQL_USER} - MYSQL_HOST=db - REDIS_HOST=redis - TZ=Europe/Berlin networks: - web depends_on: - db - redis

cron: image: nextcloud:apache restart: always volumes: - /volume1/docker/nextcloud:/var/www/html entrypoint: /cron.sh networks: - web depends_on: - app - db - redis

networks: web: external: true`

persching1978 avatar Jul 17 '22 05:07 persching1978

It's fantastic: after posting my comment I've rebooted my Diskstation and now nextcloud cron works fine. :)

persching1978 avatar Jul 17 '22 06:07 persching1978

Personally, I think docker exec is a better way, because is does not requires to change official nextcloud docker image, and automatic upgrade is possible.

lawipac avatar Jul 28 '22 07:07 lawipac

The background cron should be run in a separate container If you provide the docker-compose.yml you using I can help you with how to set up the cron container. Or the docker compose examples right here can help you. https://github.com/nextcloud/docker/blob/master/.examples/docker-compose/insecure/mariadb/apache/docker-compose.yml It should be like that

app:
  image: nextcloud:apache
  restart: always
  ports:
    - 127.0.0.1:8080:80
  volumes:
    - nextcloud:/var/www/html
  environment:
    - MYSQL_HOST=db
    - REDIS_HOST=redis
  env_file:
    - db.env
  depends_on:
    - db
    - redis

cron:
  image: nextcloud:apache
  restart: always
  volumes:
    - nextcloud:/var/www/html
  entrypoint: /cron.sh
  depends_on:
    - db
    - redis

mine doesn't work. i check the container log for the cron service and here's what i found:

cron_1         | crond: file www-data:
cron_1         | crond:  line php -f /var/www/html/cron.php
cron_1         | crond: wakeup dt=60
cron_1         | crond: file www-data:
cron_1         | crond:  line php -f /var/www/html/cron.php
cron_1         | crond:  job: 0 php -f /var/www/html/cron.php
cron_1         | crond: child running /bin/bash
cron_1         | crond: USER www-data pid  17 cmd php -f /var/www/html/cron.php
cron_1         | Exception: Not installed in /var/www/html/lib/base.php:282
cron_1         | Stack trace:
cron_1         | #0 /var/www/html/lib/base.php(663): OC::checkInstalled(Object(OC\SystemConfig))
cron_1         | #1 /var/www/html/lib/base.php(1104): OC::init()
cron_1         | #2 /var/www/html/cron.php(43): require_once('/var/www/html/l...')
cron_1         | #3 {main}
cron_1         | crond: wakeup dt=10

for reference, this is my docker-compose:

version: '3'

services:

  proxy:
    image: jwilder/nginx-proxy:alpine
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
    container_name: nextcloud-proxy
    networks:
      - nextcloud_network
    ports:
      - 24280:80
      - 24443:443
    volumes:
      - ./proxy/conf.d:/etc/nginx/conf.d:rw
      - ./proxy/vhost.d:/etc/nginx/vhost.d:rw
      - ./proxy/html:/usr/share/nginx/html:rw
      - ./proxy/certs:/etc/nginx/certs:ro
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
    environment:
      - upload_max_filesize=2048M
    restart: unless-stopped

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: nextcloud-letsencrypt
    depends_on:
      - proxy
    networks:
      - nextcloud_network
    volumes:
      - ./proxy/certs:/etc/nginx/certs:rw
      - ./proxy/vhost.d:/etc/nginx/vhost.d:rw
      - ./proxy/html:/usr/share/nginx/html:rw
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: unless-stopped

  db:
    image: mariadb
    container_name: nextcloud-mariadb
    networks:
      - nextcloud_network
    volumes:
      - ./db:/var/lib/mysql
      - /etc/localtime:/etc/localtime:ro
    environment:
      - MYSQL_ROOT_PASSWORD=*****************
      - MYSQL_PASSWORD=*****************
      - MYSQL_DATABASE=*****************
      - MYSQL_USER=*****************
    restart: unless-stopped

  app:
    image: nextcloud:latest
    container_name: nextcloud-app
    networks:
      - nextcloud_network
    depends_on:
      - letsencrypt
      - proxy
      - db
    volumes:
      - ./nextcloud_html:/var/www/html
      - ./app/config:/var/www/html/config
      - ./app/custom_apps:/var/www/html/custom_apps
      - ./app/data:/var/www/html/data
      - ./app/themes:/var/www/html/themes
      - /etc/localtime:/etc/localtime:ro
    environment:
      - VIRTUAL_HOST=*****************
      - LETSENCRYPT_HOST=*****************
      - LETSENCRYPT_EMAIL=*****************
      - PHP_MEMORY_LIMIT=2048M
      - PHP_UPLOAD_LIMIT=2048M
    restart: unless-stopped

  cron:
    image: nextcloud:apache
    restart: always
    volumes:
      - ./nextcloud_html:/var/www/html
    entrypoint: /cron.sh
    networks:
      - nextcloud_network
    depends_on:
      - letsencrypt
      - proxy
      - db

volumes:
  nextcloud:
  db:

networks:
  nextcloud_network:

wekaz avatar Aug 19 '22 11:08 wekaz

The nextcloud volumes and cron volumes must inline

martadinata666 avatar Aug 19 '22 12:08 martadinata666

The nextcloud volumes and cron volumes must inline

already did

- ./nextcloud_html:/var/www/html

wekaz avatar Aug 19 '22 12:08 wekaz

The nextcloud volumes and cron volumes must inline

already did

- ./nextcloud_html:/var/www/html

The config? The data? The custom?

martadinata666 avatar Aug 19 '22 13:08 martadinata666

so i have to add these too?

      - ./nextcloud_html:/var/www/html
      - ./app/config:/var/www/html/config
      - ./app/custom_apps:/var/www/html/custom_apps
      - ./app/data:/var/www/html/data
      - ./app/themes:/var/www/html/themes
      - /etc/localtime:/etc/localtime:ro

wekaz avatar Aug 20 '22 06:08 wekaz