Search code examples
dockertestingdocker-composeend-to-end

docker-compose execute command in sibling container


I am building an end to end test suite around a number of services. Some of these services aren't really services. They are actually procedural scripts which are run in sequence. These are executed at the command line and accept arguments, as you would expect a script to do.

We have docker images for these scripts/apps. I have compiled them into a docker-compose file. They are defined there as services which are sibling to the end to end test suite itself. So, for example:

docker-compose.yml

version: '3.4'
services:
  script:
    build: https://${GITHUB_ACCESS}:@github.com/company/script.git
    image: script:e2e
  e2e_tests:
    build: .
    image: e2e:e2e

Now, the e2e service needs to execute the script. Since the script isn't a service, I can't make a simple api call. How would I pass a command into the script container in order to execute it, from the e2e_tests container?


Solution

  • Problem

    You want to call a command (let's say echo 1) which is located inside your script container (S1, derived from the image script:e2e) from your testing container (T1, derived from the image e2e_tests:e2e)

    Solution

    You could use the possibility to expose the Docker socket to a container.

    1. Expose the Docker socket to container T1 (which should run the tests):

      docker run -it --name T1 --volume /var/run/docker.sock:/var/run/docker.sock e2e_tests:e2e
      
    2. Now from within the container T1 you are able to start other containers. This can be used to also start the script container S1 and execute a command:

      docker run --name S1 scipt:e2e echo 1
      1
      

    The output of the command (here echo 1) will be piped to T1, so you can directly parse/use it.


    How to transfer this to docker-compose.yml?

    version: '3.4'
    services:
      script:
      build: https://${GITHUB_ACCESS}:@github.com/company/script.git
      image: script:e2e
    e2e_tests:
      build: .
      image: e2e:e2e
      volumes: /var/run/docker.sock:/var/run/docker.sock
    

    Where to put the actual execution of the test (which in turn will have to execute docker run ... echo 1) depends on your specific usecase. You could:

    • execute this directly from within the CMD of e2e
    • put it into a script, which is executed by CMD of e2e
    • specify the entrypoint using the docker-compose.yml for e2e

    Security

    Be aware of the fact that the docker socket is highly privileged (it is like root). So exposing this socket might introduce security implications. It is on the same level as executing your tests on a system with password-less sudo, the tests won't get executed with privileged permissions, but an attacker which is able to modify your tests, could use it to gain privileged access. This might be ok, depending on your threat model.

    For understanding the threat, see: