Home > Back-end >  Write output of the local command into the file in the running docker container
Write output of the local command into the file in the running docker container

Time:04-13

I have file template which has various variables. I would like to constitute these variables with values before I copy this file to running container. This what I do right now:

export $(grep -v '^#' /home/user/.env | xargs) && \
    envsubst < template.yaml > new_connection.yaml && \
    docker cp new_connection.yaml docker_container:/app && \
    rm new_connection.yaml

This is working, however I'm sure there is a way I can skip file creation/copy/remove steps and do just something like: echo SOME_TEXT > new_connection.yaml straight to the container. Could you help?

CodePudding user response:

This seems like a good application for an entrypoint wrapper script. If your image has both an ENTRYPOINT and a CMD, then Docker passes the CMD as additional arguments to the ENTRYPOINT. That makes it possible to write a simple script that rewrites the configuration file, then runs the CMD:

#!/bin/sh
envsubst < template.yaml > /app/new_connection.yaml
exec "$@"

In the Dockerfile, COPY the script in and make it the ENTRYPOINT. (If your host system doesn't correctly preserve executable file permissions or Unix line endings you may need to do some additional fixups in the Dockerfile as well.)

COPY entrypoint.sh ./
ENTRYPOINT ["/app/entrypoint.sh"]  # must be JSON-array form
CMD same command as the original image

When you run the container, you need to pass in the environment file, but there's a built-in option for this

docker run --env-file /home/user/.env ... my-image

If you want to see this working, any command you provide after the image name replaces the Dockerfile CMD, but it will still be passed to the ENTRYPOINT as arguments. So you can, for example, see the rewritten config file in a new temporary container:

docker run --rm --env-file /home/user/.env my-image \
  cat /app/new_connection.yaml

CodePudding user response:

Generally, I agree with David Maze and the comment section. You should probably build your image in such a way that it picks up env vars on startup and uses them accordingly.


However, to answer your question, you can pipe the output of envsubst to the running container.

$ echo 'myVar: ${FOO}' > env.yaml
$ FOO=bar envsubst < env.yaml | docker run -i busybox cat
myVar: bar

If you want to write that to a file, using redirection, you need to wrap it in a sh -c because otherwise the redirection is treated as redirect the container output to some path on the host.

FOO=bar envsubst < env.yaml | docker run -i busybox sh -c 'cat > my-file.yaml'

I did it here with docker run but you can do the same with exec.

FOO=bar envsubst < env.yaml | docker exec -i <container> cat
  • Related