How to create a simple docker container that will be periodically sending curl requests?

Viewed 469

I have the following standalone docker-compose.yml file:

version: "3"

services:
  feed_activator:
    container_name: feed_activator
    image: docker
    volumes: [ "/var/run/docker.sock:/var/run/docker.sock" ]
    command: [ "/bin/sh", "-c", "apk --no-cache add curl", "while true; do sleep 60; curl 'https://google.com'; done" ]
    restart: "always"

what I would expect it to do is to simply install curl and send a GET request to https://google.com every minute.

What happens instead is

fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
(1/4) Installing brotli-libs (1.0.9-r3)
(2/4) Installing nghttp2-libs (1.42.0-r1)
(3/4) Installing libcurl (7.78.0-r0)
(4/4) Installing curl (7.78.0-r0)
Executing busybox-1.32.1-r6.trigger
OK: 13 MiB in 24 packages
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
OK: 13 MiB in 24 packages
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
OK: 13 MiB in 24 packages

where the

fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
OK: 13 MiB in 24 packages

part is repeating endlessly and the container is in a restarting state. What do I have to do for it to function correctly? Any hint would be much appreciated.

2 Answers

I wouldn't try to write a "standalone" Compose file like this. Every time you restart the process, it will need to reinstall the Alpine package dependencies; that's slow and wasteful and doesn't scale beyond trivial examples. This setup of writing a complex command: is also tricky to get right.

The first thing I'd do is to write an ordinary shell script that does what you want:

#!/bin/sh
# curl-periodically.sh
while true
do
  sleep 60
  curl 'https://google.com'
done

You can run this locally, outside Docker, to make sure it does what you want.

chmod +x curl-periodically.sh
./curl-periodicially.sh

You can then write a Dockerfile to turn your program into a runnable Docker image. This file should be named exactly Dockerfile.

FROM alpine

# Set up OS-level dependencies
RUN apk --no-cache add curl

# Copy the application in
WORKDIR /app
COPY curl-periodically.sh .

# Explain what to do when a container starts
CMD ["./curl-periodically.sh"]

Now your Compose setup just needs to explain that this image needs to be built. You do not need to write a complex sh -c command or bind-mount anything.

version: '3.8'
services:
  feed_activator:
    build: .
    restart: always

(Avoid bind-mounting the Docker socket into a container, using the Docker Hub docker image, and otherwise trying to manipulate containers from other containers: you can trivially root the entire host this way, and it makes your application unnecessarily tied to Docker. Something that depends on docker commands might not even run in other container systems like Kubernetes. This example doesn't seem to need it at all and I've not included it.)

The solution is to run all in one command like so

command: [ "/bin/sh", "-c", "apk --no-cache add curl; while true; do sleep 60; curl 'https://google.com'; done" ]

note the ...url", "while... to ...url; while... difference

Related