I try hard to make my integration tests run in docker containers to guarantee they are not mistakenly dependent on my system and that they test the system as if a real deployment was in place.
Sometimes a test depends on some startup string existing in the logs. An example is that my server emits an administrator temporary password for the first time the server runs. This one-time administrator password is written to stdout and docker logs <container> captures it. Unfortunately for my testing setup, when the container is destroyed and re-setup the logs are reset losing that one-time password needed by the tests. That destroy/re-setup cycle is often manual and not part of the expected flow but it happens frequently due to manual tunings.
I used to just hardcode the temporary password on the tests for when manual iteration was ongoing but this was annoying because I needed to be careful to not commit the temporary change, and because it always meant I always needed to carry over a diff with such workaround. That temporary password would actually be meaningless if it was committed and would break automated actual testing. Instead of changing code with the drawbacks above, I found a way to manually write the temporary password back to the docker logs.
The
https://docs.docker.com/engine/reference/commandline/logs/#extended-descriptiondocker logs --follow
command will continue streaming the new output from the container’sSTDOUT
andSTDERR
.
The question is how can we write to the container’s log if the container’s process itself will not do it?
By default, docker spawns a container with a process ID=1. In Linux, you can write to a process’ file descriptors as long as have the right permissions. stdout is file descriptor number 1. This means:
docker exec -it <container name> bash
echo 'magic string' > /proc/1/fd/1 # Where /proc/$PID=1/fd/fd=1(stdout0
Make sure your container is running to be able to do this, otherwise it will not work:
The
https://docs.docker.com/engine/reference/commandline/exec/docker exec
command runs a new command in a running container.
PS: I could not find a primary source documenting that PID = 1 is the default PID for a newly spawned container. Given the meaning of PID=1 in Linux it is baffling or I am making a very wrong assumption.