Pigpocket
Pigpocket

Reputation: 458

Dockerfile won't install cron

I am trying to install cron via my Dockerfile, so that docker-compose can create a dedicated cron container by using a different entrypoint when it's built, which will regularly create another container that runs a script, and then remove it. I'm trying to follow the Separating Cron From Your Application Services section of this guide: https://www.cloudsavvyit.com/9033/how-to-use-cron-with-your-docker-containers/

I know that order of operation is important and I wonder if I have that misconfigured in my Dockerfile:

FROM swift:5.3-focal as build

RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
    && apt-get -q update \
    && apt-get -q dist-upgrade -y \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /build

RUN apt-get update && apt-get install -y cron
COPY example-crontab /etc/cron.d/example-crontab
RUN chmod 0644 /etc/cron.d/example-crontab &&\
    crontab /etc/cron.d/example-crontab

COPY ./Package.* ./
RUN swift package resolve

COPY . .

RUN swift build --enable-test-discovery -c release

WORKDIR /staging

RUN cp "$(swift build --package-path /build -c release --show-bin-path)/Run" ./
RUN [ -d /build/Public ] && { mv /build/Public ./Public && chmod -R a-w ./Public; } || true
RUN [ -d /build/Resources ] && { mv /build/Resources ./Resources && chmod -R a-w ./Resources; } || true

# ================================
# Run image
# ================================
FROM swift:5.3-focal-slim

RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true && \
    apt-get -q update && apt-get -q dist-upgrade -y && rm -r /var/lib/apt/lists/*

RUN useradd --user-group --create-home --system --skel /dev/null --home-dir /app vapor

WORKDIR /app

COPY --from=build --chown=vapor:vapor /staging /app

USER vapor:vapor

EXPOSE 8080

ENTRYPOINT ["./Run"]
CMD ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]

This is relevant portion of my docker-compose file:

services:
  app:
    image: prizmserver:latest
    build:
      context: .
    environment:
      <<: *shared_environment
    volumes:
      - $PWD/.env:/app/.env
    links:
      - db:db
    ports:
      - '8080:8080'
    # user: '0' # uncomment to run as root for testing purposes even though Dockerfile defines 'vapor' user.
    command: ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]
  cron:
    image: prizmserver:latest
    entrypoint: /bin/bash
    command: ["cron", "-f"]

This is my example-scheduled-task.sh:

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

And this is my crontab file:

*/5 * * * * /usr/bin/sh /example-scheduled-task.sh

My script example-scheduled-task.sh and my crontab example-crontab live inside my application folder where this Dockerfile and docker-compose.yml live.

Why won't my cron container launch?

Upvotes: 2

Views: 1060

Answers (1)

atline
atline

Reputation: 31604

In a multistage build, only the last FROM will be used to generate final image.

E.g., for next example, the a.txt only could be seen in the first stage, can't be seen in the final image.

Dockerfile:

FROM python:3.9-slim-buster

WORKDIR /tmp
RUN touch a.txt
RUN ls /tmp

FROM ubuntu:16.04
RUN ls /tmp

Execution:

# docker build -t abc:1 . --no-cache
Sending build context to Docker daemon  2.048kB
Step 1/6 : FROM python:3.9-slim-buster
 ---> c2f204720fdd
Step 2/6 : WORKDIR /tmp
 ---> Running in 1e6ed4ef521d
Removing intermediate container 1e6ed4ef521d
 ---> 25282e6f7ed6
Step 3/6 : RUN touch a.txt
 ---> Running in b639fcecff7e
Removing intermediate container b639fcecff7e
 ---> 04985d00ed4c
Step 4/6 : RUN ls /tmp
 ---> Running in bfc2429d6570
a.txt
tmp6_uo5lcocacert.pem
Removing intermediate container bfc2429d6570
 ---> 3356850a7653
Step 5/6 : FROM ubuntu:16.04
 ---> 065cf14a189c
Step 6/6 : RUN ls /tmp
 ---> Running in 19755da110b8
Removing intermediate container 19755da110b8
 ---> 890f13e709dd
Successfully built 890f13e709dd
Successfully tagged abc:1

Back to your example, you copy crontab to the stage of swift:5.3-focal, but the final stage is swift:5.3-focal-slim which won't have any crontab.

EDIT:

For you, the compose for cron also needs to update as next:

cron:
    image: prizmserver:latest
    entrypoint: cron
    command: ["-f"]

cron don't need to use /bash to start, directly use cron to override the entrypoint could make the trick.

Upvotes: 1

Related Questions