Hi there! I think I’m using a standard Golang/Docker recipe from blog.golang.org docker
However I noticed it takes 10s to stop. And it exits with code 137.
When I exec into the running container, I noticed I try kill process 1, it doesn’t seem to quit. Why is the golang binary being run from shell? What am I missing?
The “string” form of CMD and ENTRYPOINT always run /bin/sh -c "...". (And, correspondingly, the signal docker stop sends goes to the shell, not your process, which may be why it needs to be kill -9’d.) Try the JSONish form
(If the container does other things and getting a shell in it is useful, I might prefer CMD to ENTRYPOINT. If you rebuild the program outside the container, statically link it, and build it into a FROM scratch container such that running the count binary is literally the only thing it can do, ENTRYPOINT makes sense.)
I would like to use FROM scratch, but what puzzles me… is how am I supposed to build the binary the static binary in a container to begin with? Can a Dockerfile bootstrap another?
No; but what does docker logs count say? Does it work if you just docker run from the command line? Does it work if you docker run --rm -it count bash, then run the program from there?
In my hand-built environment, every container build has a setup.sh script, which is responsible for producing a Dockerfile and whatever other artifacts are required. That can (with some care) docker run other things, and/or assume it’s being run on a Linux host with an appropriate toolchain available. In that setup, the setup.sh script can do the (static) compilation. It would look something like this:
host:~/project$ mkdir x
host:~/project$ cd x
host:~/project/x$ ../setup.sh
host:~/project/x$ ls
Dockerfile program
host:~/project/x$ cat Dockerfile
FROM scratch
MAINTAINER Me! <me@example.com>
COPY program /
ENTRYPOINT ["/program"]
EXPOSE 80
host:~/project/x$ docker build -t program .
host:~/project/x$ cd ..
host:~/project$ rm -rf x
host:~/project$ docker run -d -p 80:8080 program
I find setup.sh to be a handy hook to do any sort of build-time setup, but in my system many of the setup.sh scripts are extremely routine “copy the Dockerfile into the target directory” things. Do you care that your image contains a Go toolchain that you don’t need at runtime? If you do, the “precompile a static binary, then build a FROM scratch issue” approach is better; but it’s totally reasonable to say “that doesn’t matter to me”.
Docker layer caching is extremely handy, but it does in fact conflict badly with invoking any kind of source control operation (hg pull -u, go get). There’s a docker build option to forcibly disable it. Another advantage of the setup.sh approach is that you can run these sorts of “must run every time” commands in the setup script, and then take advantage of build caching to not re-run the actual go install compilation step if it’s not necessary.
My end goal really, is to git push my golang changes and have my container restart with the changes in the sanest and ideally fastest possible manner.
My big issue right now, is when I restart the https://github.com/kaihendry/count/blob/master/count.service it takes almost a minute to build/deploy the new Docker image, leaving quite some downtime if my little count Web application was actually a production application!