sourcecode

도커 컨테이너 내에서 cron 작업을 실행하는 방법은 무엇입니까?

codebag 2023. 8. 1. 20:30
반응형

도커 컨테이너 내에서 cron 작업을 실행하는 방법은 무엇입니까?

셸 스크립트를 호출하는 도커 컨테이너 내에서 cronjob을 실행하려고 합니다.

어제 저는 웹사이트 전체를 검색하고 스택 오버플로를 했지만, 제대로 작동하는 솔루션을 찾을 수 없었습니다.
어떻게 해야 하나요?

당신은 당신의 사할수다를 할 수 .crontab해당 이미지에서 시작된 컨테이너가 작업을 실행하기 위해 이미지로 이동합니다.


중요: 도커-크론 문제 3에서 언급한 바와 같이, CRLF가 아닌 LF를 사용합니다.cronjava.


Julien Boulay의 "Run cron job with Docker"를 참조하십시오.

을▁called▁""▁a▁file▁new▁let니합성'"라는 새로운 파일을 봅시다.hello-cron우리의 직업을 묘사하기 위해.

# must be ended with a new line "LF" (Unix) and not "CRLF" (Windows)
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.

여러분이 궁금면다하지인이 ,2>&1 아이만 휴리가 설명합니다.

다음 도커 파일은 이미지를 빌드하는 모든 단계를 설명합니다.

FROM ubuntu:latest
MAINTAINER docker@ekito.fr

RUN apt-get update && apt-get -y install cron

# Copy hello-cron file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron
 
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron

# Apply cron job
RUN crontab /etc/cron.d/hello-cron
 
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
 
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log

그러나: 죽으면 용기가 계속 실행됩니다.

(Gaafar의견설치 소음을 줄이려면 어떻게 해야 합니까?:
apt-get -y install -qq --force-yes cron작동할 수도 있음

Nathan Lloyd가 논평에서 언급한 바와 같이:

갓챠에 대한 간단한 메모:
에는 "cron"을 기억하십시오.
RUN chmod 0744 /the_script
Cron은 잊어버리면 자동으로 실패합니다.


또는 hugoShaka답변에 설명된 대로 작업 자체를 로그 파일이 아닌 stdout/stderr로 직접 리디렉션하십시오.

 * * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2

마지막 도커 파일 줄 바꾸기

CMD ["cron", "-f"]

그러나 태스크를 비루트로 실행하려는 경우에는 작동하지 않습니다.

항목: (정보)cron -f즉, cron "forground") "unbutu가 작동하지 않습니다."


빌드 및 실행:

sudo docker build --rm -t ekito/cron-example .
sudo docker run -t -i ekito/cron-example

인내심을 갖고 2분 동안 기다린 후 명령줄에 다음과 같은 내용이 표시됩니다.

Hello world
Hello world

에릭다음과 같이 덧붙입니다.

로 참은 다음과 같습니다.tail이미지 빌드 중에 올바른 파일이 생성되면 해당 파일이 표시되지 않을 수 있습니다.
그런 경우, 테일이 올바른 파일을 선택하려면 컨테이너 런타임 중에 파일을 만들거나 터치해야 합니다.

"도커 끝의 출력이 표시되지 않습니다."를 참조하십시오.


제이슨 쿨라퉁가의 "런닝 크론 인 도커"(2021년 4월)에서 더 자세히 보기.

다음을 기반으로 한 Jason의 이미지 보기:

  • 파일 중cronie/crond분포에 따라

  • 초화하진점입을 /etc/environment그리고 나서 부르는 것.

    cron -f -l 2
    

허용된 답변은 프로덕션 환경에서 위험할 수 있습니다.

도커에서는 컨테이너당 하나의 프로세스만 실행해야 합니다. 그렇지 않으면 포크되고 백그라운드로 이동한 프로세스가 모니터링되지 않고 사용자 모르게 중지될 수 있기 때문입니다.

를 할 때CMD cron && tail -f /var/log/cron.log를 실행하기 fork를 .cron▁in▁exits▁execute▁you다▁the니있▁process▁let▁main▁and습▁back수ground,를 실행할 수 있습니다.tailf에:할 수 가 여전히 가 다시.백그라운드 크론 프로세스가 중지되거나 실패할 수 있으며, 컨테이너는 여전히 자동으로 실행되고 오케스트레이션 도구가 다시 시작하지 않습니다.

cron으로 리디렉션하면 수 .stdout그리고.stderr은 각각 위는치각의에 ./proc/1/fd/1그리고./proc/1/fd/2.

기본 셸 리디렉션을 사용하여 다음과 같은 작업을 수행할 수 있습니다.

* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2

는 다음과 CMD ["cron", "-f"]

그러나 태스크를 비루트로 실행하려는 경우에는 작동하지 않습니다.

간단하고 가벼운 이미지를 사용하려는 사용자:

FROM alpine:3.6

# copy crontabs for root user
COPY config/cronjobs /etc/crontabs/root

# start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]

여기서 cronjobs는 다음 형식으로 cronjobs가 포함된 파일입니다.

* * * * * echo "hello stackoverflow" >> /test_file 2>&1
# remember to end this file with an empty new line

하지만 보아하니 당신은 보지 못할 것입니다.hello stackoverflowdocker logs.

@VonC가 제안한 것은 좋지만 나는 모든 cron 작업 구성을 한 줄로 하는 것을 선호합니다.이렇게 하면 cron 작업 위치와 같은 플랫폼 간 문제를 피할 수 있으며 별도의 cron 파일이 필요하지 않습니다.

FROM ubuntu:latest

# Install cron
RUN apt-get -y install cron

# Create the log file to be able to run tail
RUN touch /var/log/cron.log

# Setup cron job
RUN (crontab -l ; echo "* * * * * echo "Hello world" >> /var/log/cron.log") | crontab

# Run the command on container startup
CMD cron && tail -f /var/log/cron.log

도커 컨테이너를 실행한 후 cron 서비스가 다음을 통해 작동하는지 확인할 수 있습니다.

# To check if the job is scheduled
docker exec -ti <your-container-id> bash -c "crontab -l"
# To check if the cron service is running
docker exec -ti <your-container-id> bash -c "pgrep cron"

CMD 대신 ENTRYPOINT를 사용하려는 경우 위의 CMD를 다음으로 대체할 수 있습니다.

ENTRYPOINT cron start && tail -f /var/log/cron.log

그러나: 죽으면 용기가 계속 실행됩니다.

다른 방법으로는 cron(스케줄러)을 지원하는 태스크 실행기인 태스커를 사용하는 것이 있습니다.

왜냐고요? 때때로 cron 작업을 실행하려면 기본 이미지(파이톤, 자바, 노드js, 루비)를 cron과 혼합해야 합니다.그것은 유지해야 할 또 다른 이미지를 의미합니다.태스커는 크론드와 사용자 컨테이너를 분리하여 이를 방지합니다.명령을 실행할 이미지에 초점을 맞추고 이를 사용하도록 태스커를 구성하면 됩니다.

에 기여가 .docker-compose.yml를 위해 몇 입니다.

version: "2"

services:
    tasker:
        image: strm/tasker
        volumes:
            - "/var/run/docker.sock:/var/run/docker.sock"
        environment:
            configuration: |
                logging:
                    level:
                        ROOT: WARN
                        org.springframework.web: WARN
                        sh.strm: DEBUG
                schedule:
                    - every: minute
                      task: hello
                    - every: minute
                      task: helloFromPython
                    - every: minute
                      task: helloFromNode
                tasks:
                    docker:
                        - name: hello
                          image: debian:jessie
                          script:
                              - echo Hello world from Tasker
                        - name: helloFromPython
                          image: python:3-slim
                          script:
                              - python -c 'print("Hello world from python")'
                        - name: helloFromNode
                          image: node:8
                          script:
                              - node -e 'console.log("Hello from node")'

여기에는 3개의 작업이 있으며, 모든 작업이 매 분마다 실행됩니다.every: minute , , , , 를 각각 입니다.script코드, 정의된 이미지 내부image부분.

그냥 도망가docker-compose up작동하는 것을 확인합니다.다음은 전체 설명서가 포함된 태스커 레포입니다.

http://github.com/opsxcq/tasker

Docker's Docker를 통해 중인 ,exec인터페이스, 이것은 당신이 관심을 가질 수 있습니다.

컨테이너를 관찰하고 메타데이터에 정의된 작업을 스케줄링하는 데몬을 작성했습니다.예:

version: '2'

services:
  wordpress:
    image: wordpress
  mysql:
    image: mariadb
    volumes:
      - ./database_dumps:/dumps
    labels:
      deck-chores.dump.command: sh -c "mysqldump --all-databases > /dumps/dump-$$(date -Idate)"
      deck-chores.dump.interval: daily

'Classic', cron과 같은 구성도 가능합니다.

여기 문서들이 있고, 여기 이미지 저장소가 있습니다.

윈도우용 도커를 사용하는 경우 crontab 파일을 윈도우에서 unbuntu 컨테이너로 가져오려면 CRLF에서 LF(즉, dos에서 unix)로 줄바꿈 형식을 변경해야 합니다.그렇지 않으면 cron 작업이 작동하지 않습니다.다음은 작동하는 예입니다.

FROM ubuntu:latest

RUN apt-get update && apt-get -y install cron
RUN apt-get update && apt-get install -y dos2unix

# Add crontab file (from your windows host) to the cron directory
ADD cron/hello-cron /etc/cron.d/hello-cron

# Change line ending format to LF
RUN dos2unix /etc/cron.d/hello-cron

# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron

# Apply cron job
RUN crontab /etc/cron.d/hello-cron

# Create the log file to be able to run tail
RUN touch /var/log/hello-cron.log

# Run the command on container startup
CMD cron && tail -f /var/log/hello-cron.log

도커 컨테이너에서 cron 작업을 디버깅하는 것은 지루한 작업이기 때문에 이것을 알아내는 데 실제로 몇 시간이 걸렸습니다.코드가 작동하지 않는 다른 사람들에게 도움이 되기를 바랍니다!

그러나: 죽으면 용기가 계속 실행됩니다.

VonC의 대답은 꽤 철저합니다.추가로 저에게 도움이 된 한 가지를 추가하고 싶습니다.파일을 미행하지 않고 cron 작업을 실행하려는 경우 해당 작업을 제거할 수 있습니다.&& tail -f /var/log/cron.log.cron 파일 이름입니다.

그러나 cron 명령이 완료되면 Docker는 마지막 명령이 종료되었다고 생각하므로 Docker 컨테이너가 실행된 직후에 종료됩니다.이 문제는 다음을 통해 포그라운드에서 cron을 실행하면 피할 수 있습니다.cron -f.

불행하게도, 위의 답변들 중 어떤 것도 저에게 효과가 없었습니다. 비록 모든 답변들이 해결책으로 이어지고 결국 제 해결책으로 이어지지만, 누군가에게 도움이 된다면 여기에 그 토막글이 있습니다.감사해요.

이 문제는 bash 파일로 해결할 수 있습니다. Docker의 계층화된 아키텍처로 인해 cron 서비스가 RUN/CMD/ENTRYPOINT 명령으로 시작되지 않습니다.

cron 및 기타 서비스를 시작할 bash 파일을 추가하기만 하면 됩니다(필요한 경우).

도커 파일

FROM gradle:6.5.1-jdk11 AS build
# apt
RUN apt-get update
RUN apt-get -y install cron
# Setup cron to run every minute to print (you can add/update your cron here)
RUN touch /var/log/cron-1.log
RUN (crontab -l ; echo "* * * * * echo testing cron.... >> /var/log/cron-1.log 2>&1") | crontab
# entrypoint.sh
RUN chmod +x entrypoint.sh
CMD ["bash","entrypoint.sh"]

entrypoint.sh

#!/bin/sh
service cron start & tail -f /var/log/cron-2.log

cron과 함께 해당 합니다.& 다음과 같은 명령을 할 수 있습니다./opt/wildfly/bin/standalone.sh & service cron start & tail -f /var/log/cron-2.log

일단 당신이 그곳의 도커 컨테이너에 들어가면 당신은 그것을 볼 수 있습니다.testing cron....됩니다./var/log/cron-1.log

하지만, 죽으면, 용기는 계속 작동합니다.

다른 답변을 바탕으로 도커 이미지를 만들었는데, 다음과 같이 사용할 수 있습니다.

docker run -v "/path/to/cron:/etc/cron.d/crontab" gaafar/cron

/path/to/cron파일의 파일의 할 수 . crontab 파일 crontab 파일의 Docker 파일 이름은 Docker 파일 이름입니다.

FROM gaafar/cron

# COPY crontab file in the cron directory
COPY crontab /etc/cron.d/crontab

# Add your commands here

참고로, 이미지는 여기 있습니다.

docker exec을 통해 서비스에 대한 명령을 실행하는 전용 컨테이너에서 cronjob을 정의합니다.

이는 더 높은 응집력이며 실행 중인 스크립트는 서비스에 대해 정의한 환경 변수에 액세스할 수 있습니다.

#docker-compose.yml
version: "3.3"
services:
    myservice:
      environment:
        MSG: i'm being cronjobbed, every minute!
      image: alpine
      container_name: myservice
      command: tail -f /dev/null

    cronjobber:
     image: docker:edge
     volumes:
      - /var/run/docker.sock:/var/run/docker.sock
     container_name: cronjobber
     command: >
          sh -c "
          echo '* * * * * docker exec myservice printenv | grep MSG' > /etc/crontabs/root
          && crond -f"

가장 작은 이미지 중 하나이기 때문에 저는 busybox를 사용하기로 결정했습니다.

crond는 포그라운드(-f)에서 실행되고, 로깅은 stderr(-d)로 전송되며, 로그 수준을 변경하도록 선택하지 않았습니다. crontab 파일이 기본 경로: /var/spool/cron/crontabs로 복사됩니다.

FROM busybox:1.33.1

# Usage: crond [-fbS] [-l N] [-d N] [-L LOGFILE] [-c DIR]
#
#   -f  Foreground
#   -b  Background (default)
#   -S  Log to syslog (default)
#   -l N    Set log level. Most verbose 0, default 8
#   -d N    Set log level, log to stderr
#   -L FILE Log to FILE
#   -c DIR  Cron dir. Default:/var/spool/cron/crontabs

COPY crontab /var/spool/cron/crontabs/root

CMD [ "crond", "-f", "-d" ]

그나작의에출볼서없다니습수력은러업다에서 볼 수 .docker logs.

다른 호스트에 컨테이너를 배포할 때는 프로세스가 자동으로 시작되지 않습니다.'cron' 서비스가 컨테이너 안에서 실행되고 있는지 확인해야 합니다.우리의 경우, 저는 다른 서비스와 함께 Supervisord를 사용하여 cron 서비스를 시작하고 있습니다.

[program:misc]
command=/etc/init.d/cron restart
user=root
autostart=true
autorestart=true
stderr_logfile=/var/log/misc-cron.err.log
stdout_logfile=/var/log/misc-cron.out.log
priority=998

위의 예에서 저는 다음과 같은 조합을 만들었습니다.

나노에서 크론탭을 사용한 알파인 이미지 & 편집 (나는 vi가 싫다)

FROM alpine

RUN apk update
RUN apk add curl nano

ENV EDITOR=/usr/bin/nano 

# start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]

# Shell Access
# docker exec -it <CONTAINERID> /bin/sh

# Example Cron Entry
# crontab -e
# * * * * * echo hello > /proc/1/fd/1 2>/proc/1/fd/2
# DATE/TIME WILL BE IN UTC

일회성 작업과 병렬로 cron 설정

정기적으로 실행되어야 하는 작업을 포함하는 스크립트 파일(예: run.sh )을 생성합니다.

#!/bin/bash
timestamp=`date +%Y/%m/%d-%H:%M:%S`
echo "System path is $PATH at $timestamp"

저장하고 종료합니다.

CMD 대신 Entrypoint 사용

도커 컨테이너화 중에 시작할 여러 작업이 있는 경우 진입점 파일을 사용하여 모든 작업을 실행합니다.

진입점 파일은 도커 실행 명령이 실행될 때 실행되는 스크립트 파일입니다.따라서 실행하려는 모든 단계를 이 스크립트 파일에 넣을 수 있습니다.

예를 들어 다음과 같은 두 가지 작업을 실행해야 합니다.

실행 작업: "도커 컨테이너가 시작되었습니다"라는 에코가 표시됩니다.

정기 작업 실행: run.sh

entrypoint.sh 만들기

#!/bin/bash

# Start the run once job.
echo "Docker container has been started"

# Setup a cron schedule
echo "* * * * * /run.sh >> /var/log/cron.log 2>&1
# This extra line makes it a valid cron" > scheduler.txt

crontab scheduler.txt
cron -f

파일에 설정된 crontab에 대해 설명하겠습니다.

* * * * *크론 예약. 매 분마다 작업을 실행해야 합니다.요구 사항에 따라 일정을 업데이트할 수 있습니다.

/run.sh입니다.

/var/log/cron.log예약된 cron 작업의 출력을 저장할 파일 이름입니다.

2>&1오류 로그(있는 경우)도 위에서 사용한 것과 동일한 출력 파일로 리디렉션됩니다.

참고: 새 줄을 추가하는 것을 잊지 마십시오. 새 줄은 유효한 cron이 됩니다.Scheduler.txt전체 cron 설정이 파일로 리디렉션됩니다.

cron에서 시스템/사용자 관련 환경 변수 사용

실제 cron 작업은 환경 변수가 docker run 명령으로 전달될 때 대부분의 인수를 예상했습니다.하지만 bash로 인해 시스템 또는 도커 컨테이너에 속하는 환경 변수를 사용할 수 없었습니다.

그런 다음 이 문제에 대한 해결책으로 제시되었습니다.

  1. entrypoint.sh 에 다음 행을 추가합니다.
declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env
  1. cron 설정을 업데이트하고 다음을 지정합니다.
SHELL=/bin/bash
BASH_ENV=/container.env

당신의 내침의, 신당마.entrypoint.sh 합야니처다여처럼 보여야 .

#!/bin/bash

# Start the run once job.
echo "Docker container has been started"

declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env

# Setup a cron schedule
echo "SHELL=/bin/bash
BASH_ENV=/container.env
* * * * * /run.sh >> /var/log/cron.log 2>&1
# This extra line makes it a valid cron" > scheduler.txt

crontab scheduler.txt
cron -f

마지막이지만 중요한 것은:도커 파일 만들기

FROM ubuntu:16.04
MAINTAINER Himanshu Gupta

# Install cron
RUN apt-get update && apt-get install -y cron

# Add files
ADD run.sh /run.sh
ADD entrypoint.sh /entrypoint.sh
 
RUN chmod +x /run.sh /entrypoint.sh

ENTRYPOINT /entrypoint.sh

바로 그거야.도커 이미지를 빌드하고 실행합니다!

제 여기내입니다.docker-compose기반 솔루션:

  cron:
    image: alpine:3.10
    command: crond -f -d 8
    depends_on:
      - servicename
    volumes:
      - './conf/cron:/etc/crontabs/root:z'
    restart: unless-stopped

은 cron 항이 라인은에 ../conf/cronjava.

참고: 이 기능은 에 없는 명령을 실행하지 않습니다.alpine 이미지

또한 작업의 출력이 다음에 나타나지 않습니다.docker logs.

이 질문은 답이 많지만, 어떤 것은 복잡하고 또 다른 것은 단점이 있습니다.저는 문제점을 설명하고 해결책을 전달하려고 노력합니다.

cron-entrypoint.sh:

#!/bin/bash

# copy machine environment variables to cron environment
printenv | cat - /etc/crontab > temp && mv temp /etc/crontab

## validate cron file
crontab /etc/crontab

# cron service with SIGTERM support
service cron start
trap "service cron stop; exit" SIGINT SIGTERM

# just dump your logs to std output
tail -f  \
    /app/storage/logs/laravel.log \
    /var/log/cron.log \
    & wait $!

해결된 문제

  • 환경 변수는 cron 환경에서 사용할 수 없습니다(예: 환경 변수 또는 kubernetes 암호).
  • crontab 파일이 유효하지 않을 때 중지
  • 시스템이 SIGTERM 신호를 수신할 때 cron 작업을 정상적으로 중지

문맥상, 나는 라라벨 앱으로 쿠베르네테스의 이전 스크립트를 사용합니다.

다한직업다의있가다습니지고을존성양양과한▁and▁with다▁multiple.zsh그리고.curl이것은 다른 답변의 모범 사례를 결합하는 동시에 좋은 접근 방식입니다.파일: 이렇게 .+x에 대한 실행 myScript.sh그것은 새로운 환경에서 놓치기 쉽습니다.

cron.dockerfile

FROM ubuntu:latest

# Install dependencies
RUN apt-get update && apt-get -y install \
  cron \
  zsh \
  curl;

# Setup multiple jobs with zsh and redirect outputs to docker logs
RUN (echo "\
* * * * * zsh -c 'echo "Hello World"' 1> /proc/1/fd/1 2>/proc/1/fd/2 \n\
* * * * * zsh /myScript.sh 1> /proc/1/fd/1 2>/proc/1/fd/2 \n\
") | crontab

# Run cron in forground, so docker knows the task is running
CMD ["cron", "-f"]

도커 구성과 통합하면 다음과 같습니다.

docker-compose.yml

services:
  cron:
    build:
      context: .
      dockerfile: ./cron.dockerfile
    volumes:
      - ./myScript.sh:/myScript.sh

다음을 수행해야 합니다.docker compose build cron의 할 때cron.dockerfile 다음과 같이 변경됩니다.myScript.sh컴포지트에 장착된 상태로 바로 반영됩니다.

이 대사는 제가 사전 테스트 작업을 수행하는 데 도움이 되었습니다.

ADD mycron/root /etc/cron.d/root

RUN chmod 0644 /etc/cron.d/root

RUN crontab /etc/cron.d/root

RUN touch /var/log/cron.log

CMD ( cron -f -l 8 & ) && apache2-foreground # <-- run cron

--> 내 프로젝트는 내부에서 실행됩니다: FROM php:7.2-apache

그러나: 죽으면 용기가 계속 실행됩니다.

나는 가끔 그것을 찾으려고 노력했습니다.docker한 -친숙한cron했을 때그리고 마지막으로 시도했을 때, 저는 커플을 찾았습니다.

타고docker 제 "은 -친한제말은," "의근산과다볼수있다습니서음에은물출제▁-▁"▁-▁of▁be다있니▁can▁in▁seen습output친▁i"에서 볼 수 있습니다.docker logs속임수를 쓸 필요가 없습니다."

제가 지금 가장 기대되는 것은.crontab 파일을 제공할 수 있습니다. 모든 동안docker붙임성 있는사용 방법:

docker-compose.yml:

services:
  supercronic:
    build: .
    command: supercronic crontab

Dockerfile:

FROM alpine:3.17
RUN set -x \
    && apk add --no-cache supercronic shadow \
    && useradd -m app
USER app
COPY crontab .

crontab:

* * * * * date

조금 더 많은 정보가 있는 요지.

또 다른 좋은 점은 YAML을 사용한다는 것입니다.

ofelia 사용할 수 있지만 개별 컨테이너에서 작업을 실행하는 데 중점을 두는 것 같습니다.이것은 아마도 단점은 아닐 것입니다. 하지만 제가 왜 그렇게 하고 싶은지는 잘 모르겠습니다.

그리고 많은 전통적인 것들이 있습니다.cron구현: , , . 하지만 "작업의 출력을 쉽게 볼 수 있는 방법이 없습니다."

그래서 저의 문제도 마찬가지였습니다. 사항은 수정사의섹변것경이다니습었는하션을령의 이었습니다.docker-compose.yml.

부터

명령: crontab /etc/crontab && tail -f /etc/crontab

로.

명령: crontab /etc/crontab

명령: tail -f /etc/crontab

문제는 명령 사이의 '&&'이었습니다.이것을 삭제한 후에는 문제가 없었습니다.

수신 시 cron 작업을 정상적으로 중지하는 데 집중SIGTERM또는SIGQUIT 호예신(중: 실행중)를 실행할 때)docker stop).

그건 너무 쉽지 않아요.기본적으로 cron 프로세스는 실행 중인 cron 작업에 주의하지 않고 종료되었습니다.는 파보르스크의 대답을 자세히 설명하고 있습니다.

Dockerfile:

FROM ubuntu:latest

RUN apt-get update \
    && apt-get -y install cron procps \
    && rm -rf /var/lib/apt/lists/*

# Copy cronjobs file to the cron.d directory
COPY cronjobs /etc/cron.d/cronjobs

# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/cronjobs

# similarly prepare the default cronjob scripts
COPY run_cronjob.sh /root/run_cronjob.sh
RUN chmod +x /root/run_cronjob.sh
COPY run_cronjob_without_log.sh /root/run_cronjob_without_log.sh
RUN chmod +x /root/run_cronjob_without_log.sh

# Apply cron job
RUN crontab /etc/cron.d/cronjobs

# to gain access to environment variables, we need this additional entrypoint script
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# optionally, change received signal from SIGTERM TO SIGQUIT
#STOPSIGNAL SIGQUIT

# Run the command on container startup
ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh:

#!/bin/bash
# make global environment variables available within crond, too
printenv | grep -v "no_proxy" >> /etc/environment

# SIGQUIT/SIGTERM-handler
term_handler() {
  echo 'stopping cron'
  service cron stop
  echo 'stopped'
  echo 'waiting'
  x=$(($(ps u -C run_cronjob.sh | wc -l)-1))
  xold=0
  while [ "$x" -gt 0 ]
  do
    if [ "$x" != "$xold" ]; then
      echo "Waiting for $x running cronjob(s):"
      ps u -C run_cronjob.sh
      xold=$x
      sleep 1
    fi
    x=$(($(ps u -C run_cronjob.sh | wc -l)-1))
  done
  echo 'done waiting'
  exit 143; # 128 + 15 -- SIGTERM
}

# cron service with SIGTERM and SIGQUIT support
service cron start
trap "term_handler" QUIT TERM

# endless loop
while true
do
  tail -f /dev/null & wait ${!}
done

cronjobs

* * * * * ./run_cronjob.sh cron1
*/2 * * * * ./run_cronjob.sh cron2
*/3 * * * * ./run_cronjob.sh cron3

을 모두 cron으로 합니다.run_cronjob.sh 정상적으로할 수 .이렇게 하면 종료가 정상적으로 대기할 임의 코드를 실행할 수 있습니다.

run_cronjobs.sh를 깨끗하게 유지하기 선택적 job"이라는 단어가 있습니다.)

#!/bin/bash

DIR_INCL="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR_INCL" ]]; then DIR_INCL="$PWD"; fi
cd "$DIR_INCL"

# redirect all cronjob output to docker
./run_cronjob_without_log.sh "$@" > /proc/1/fd/1 2>/proc/1/fd/2

run_cronjob_without_log.sh

your_actual_cronjob_src()

때, 받을를그때를 받습니다.SIGKILL컨테이너는 여전히 즉시 종료됩니다.그런 식으로 다음과 같은 명령을 사용할 수 있습니다.docker-compose stop -t 60 cron-container정상적으로 동안 초과 됩니다. .cron 작업은 60초 동안 종료됩니다.

'cron' 자체가 UID 0을 요청하므로 모든 응답에는 컨테이너 내부의 루트 액세스가 필요합니다. 루트 액세스(예: sudo 경유)를 요청하는 것은 도커 모범 사례에 위배됩니다.예약된 작업을 관리하기 위해 https://github.com/gjcarneiro/yacron 을 사용했습니다.

액세스를 때하고 sudoers로 .sudo cron

FROM node:8.6.0
RUN apt-get update && apt-get install -y cron sudo

COPY crontab /etc/cron.d/my-cron
RUN chmod 0644 /etc/cron.d/my-cron
RUN touch /var/log/cron.log

# Allow node user to start cron daemon with sudo
RUN echo 'node ALL=NOPASSWD: /usr/sbin/cron' >>/etc/sudoers

ENTRYPOINT sudo cron && tail -f /var/log/cron.log

누군가에게 도움이 될 수도 있습니다.

그러나: 죽으면 용기가 계속 실행됩니다.

이미지를 사용할 수 있는 답변 목록에 추가하면 됩니다. https://hub.docker.com/repository/docker/cronit/simple-cron

다음과 같이 사용하여 cron 작업을 시작하는 기준으로 사용합니다.

FROM cronit/simple-cron # Inherit from the base image
#Set up all your dependencies 
COPY jobs.cron ./ # Copy your local config

분명히, cron을 (루트 사용자 아래에서) 다른 프로세스와 함께 컨테이너 내부의 프로세스로 실행할 수 있습니다.ENTRYPOINT에 있는 (Docker 문일파)start.shprocess cron start자세한 내용은 여기에 있습니다.

#!/bin/bash

# copy environment variables for local use
env >> etc/environment

# start cron service
service cron start

# start other service
service other start
#...

이미지에 데몬이 없는 경우(따라서 짧은 실행 스크립트 또는 프로세스만 해당), 단순히 cron 정보와 스케줄러 자체로 LABEL을 정의하여 외부에서 cron을 시작하는 것도 고려할 수 있습니다.이렇게 하면 기본 컨테이너 상태가 "종료"가 됩니다.스크립트가 여러 개인 경우 병렬 실행 cron 인스턴스가 여러 개인 경우보다 시스템의 설치 공간이 줄어들 수 있습니다.

참조: https://github.com/JaciBrunning/docker-cron-label

도커-구성 예제.음:

version: '3.8'

# Example application of the cron image
services:
  cron:
    image: jaci/cron-label:latest
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/etc/localtime:/etc/localtime:ro"

  hello:
    image: hello-world
    restart: "no"
    labels:
      - "cron.schedule=* * * * * "

저는 제가 더 유연하다고 생각한 다른 제안들 중 일부의 전형적인 것에 대한 수정을 공유하고 싶었습니다.환경 변수를 사용하여 cron 시간을 변경할 수 있도록 설정하고 싶었지만 cron-f로 호출하기 전에 entrypoint.sh 내에서 실행되는 스크립트를 추가했습니다.

*updatecron.sh*
#!/bin/sh
#remove old cron files
rm -rf /etc/cron.*/*
#create a new formatted cron definition
echo "$crondef [appname] >/proc/1/fd/1 2>/proc/1/fd/2" >> /etc/cron.d/restart-cron
echo \ >> /etc/cron.d/restart-cron
chmod 0644 /etc/cron.d/restart-cron
crontab /etc/cron.d/restart-cron

그러면 기존 cron 파일이 제거되고 crondef의 ENV 변수를 사용하여 새 cron 파일이 생성된 다음 로드됩니다.

Our's는 cron 작업으로 실행되는 nodejs 응용 프로그램이었으며 환경 변수에도 의존했습니다.

아래의 해결책이 우리에게 효과가 있었습니다.

도커 파일:

# syntax=docker/dockerfile:1
FROM node:12.18.1
ENV NODE_ENV=production

COPY ["startup.sh", "./"]

# Removed steps to build the node js application

#--------------- Setup cron ------------------
# Install Cron
RUN apt-get update
RUN apt-get -y install cron
 
# Run every day at 1AM
#/proc/1/fd/1 2>/proc/1/fd/2 is used to redirect cron logs to standard output and standard error
RUN (crontab -l ; echo "0 1 * * * /usr/local/bin/node /app/dist/index.js  > /proc/1/fd/1 2>/proc/1/fd/2") | crontab
    
#--------------- Start Cron ------------------
# Grant execution rights
RUN chmod 755 startup.sh
CMD ["./startup.sh"]

시작합니다.sh:

!/bin/bash
echo "Copying env variables to /etc/environment so that it is available for cron jobs"
printenv >> /etc/environment
echo "Starting cron"
cron -f

간단한 php-fpm 이미지를 사용하려는 사람들:

FROM php:7.4-fpm

RUN apt-get update \
&& apt-get install -y cron\ 
...

# Copy your cronjob file
COPY /cron/cronjob /etc/cron.d/crontab
COPY /cron/log /var/log

# owner can read and write into the crontab, group and others can read it
RUN chmod 0644 /etc/cron.d/crontab
# running our crontab using the binary from the package we installed
RUN /usr/bin/crontab /etc/cron.d/crontab

CMD cron && docker-php-entrypoint php-fpm

파일:docker-compose.yml 파일에서 하려면 이 .&& docker-php-entrypoint php-fpm

그렇지 않으면 nginx 이미지에 의한 502 불량 게이트웨이 문제(업스트림에 연결하는 동안 111: 연결이 거부됨)라는 오류가 발생했습니다.

이것이 누군가에게 도움이 되기를 바랍니다.

언급URL : https://stackoverflow.com/questions/37458287/how-to-run-a-cron-job-inside-a-docker-container

반응형