Pibmy
Pibmy

Reputation: 67

How to use timeout in dockerfile with alpine base?

Context

I'm writing a dockerfile where I run a server application based on alpine:3.9 docker image. I test if my application is correctly installed by running it and sending a GET request with curl.

I send requests until I get an answer. So in case of trouble I want to timeout my tests using the built-in timeout function.

Pre-requirements

I'm using docker version 19.03.4, build 9013bf583a on debian.

Problem

The command:

docker run --rm -it alpine:3.9 timeout -t 2 /bin/sh -c 'sleep 5; echo "Not to be seen..."'

Exit displaying Not to be seen....

If I use timeout this way, the timeout seems to be ignored... I got the same problem if I put this in a docker file.

FROM alpine:3.9
RUN timeout -t 2 /bin/sh -c 'sleep 5; echo "Not to be seen..."'
docker build -t test .

Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM alpine:3.9
 ---> 055936d39205
Step 2/2 : RUN timeout -t 2 /bin/sh -c 'sleep 5; echo "Not to be seen..."'
 ---> Running in 0fa22cd02173
Not to be seen...
Removing intermediate container 0fa22cd02173
 ---> e88107c3811b
Successfully built e88107c3811b
Successfully tagged test:latest

We can see the Not to be seen... displayed in console.

How to solve this issue ?

Reflexions / Tests

I test multiple things and the timeout function works well. It should be a problem when using it in dockerfile or passing it in docker run function...


When I try:

docker run --rm -it alpine:3.9 /bin/sh
# Then in container
timeout -t 2 /bin/sh -c 'sleep 5; echo "Not to be seen..."'

Exit with status code 143. And display Terminated.


When I try:

docker run --rm --name test -td alpine:3.9 /bin/sh
docker exec -it test timeout -t 2 /bin/sh -c 'sleep 5; echo "Not to be seen..."'

Exit with status code 143. Nothing displayed as expected.

Upvotes: 2

Views: 4682

Answers (3)

Kiruthika kanagarajan
Kiruthika kanagarajan

Reputation: 944

Timeout option in Dockerfile, you can embed timeout <value> directly for commands in Dockerfile

Eg:

ARG GOLANG=golang:1.16.4-alpine3.12
FROM ${GOLANG}
RUN timeout 60 curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh```

Upvotes: 0

Pibmy
Pibmy

Reputation: 67

In a dockerfile context, pb can be solve using https://github.com/krallin/tini tool.

Using following Dockerfile:

FROM alpine:3.9
RUN apk add --no-cache tini
RUN /sbin/tini timeout -t 2 /bin/sh -c 'sleep 5; echo "Not to be seen..."'

Executing docker build .

Result

Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM alpine:3.9
 ---> 055936d39205
Step 2/3 : RUN apk add --no-cache tini
 ---> Running in 018e342caa67
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz
(1/1) Installing tini (0.18.0-r0)
Executing busybox-1.29.3-r10.trigger
OK: 6 MiB in 15 packages
Removing intermediate container 018e342caa67
 ---> 915c3d5dc7fe
Step 3/3 : RUN /sbin/tini timeout -t 2 /bin/sh -c 'sleep 5; echo "Not to be seen..."'
 ---> Running in 3852a4f6a43d
The command '/bin/sh -c /sbin/tini timeout -t 2 /bin/sh -c 'sleep 5; echo "Not to be seen..."'' returned a non-zero code: 143

As seen the build has stoped with code 143.

The solution impose using external tool. Feel free to propose, if there is a more straight away solution.

PS: Thanks to @Eduardo Baitello for setting me on the right path :)

Upvotes: 1

Eduardo Baitello
Eduardo Baitello

Reputation: 11346

Many programs drop default signal handlers when running as PID 1 (including /bin/sh).

You need to use the --init flag in order to make the container exit properly:

--init Run an init inside the container that forwards signals and reaps processes

This should work:

docker run --rm -it --init alpine:3.9 timeout -t 2 /bin/sh -c 'sleep 5; echo "Not to be seen..."'

Upvotes: 2

Related Questions