No, you cannot expose ports to the host, either with Docker or Docker Compose, if you are using the Docker executor. The reason for this is that the outer-level Docker would need to run in a privileged mode of some kind, which would present security issues.
You can:
Switch to the Machine executor where you can run Docker in an isolated VM
Use docker exec to reach into a running container and run things
Bake your tests and test programs into an existing image, and run them inside an image
Put your tests and test programs into a new image, and connect to your SUT via the internal Docker network
Thanks for the quick reply! As I understand
(1) may become expensive ( https://circleci.com/docs/2.0/executor-types/#using-machine ). Also I already made a custom docker image to run my tests with the utilities needed and would have to replicate that
(2) will not work in my case (I don’t want to exec, I need a database connection etc.)
(3) you mean making a docker image with my DB and message queue for test? I am not sure chaining commands would work so well (ie. CMD ./my-db && config_env && ./my-mq in my dockerfile) but this could work
(4) not 100% sure what you mean - it could be the bit I am missing, can you please elaborate a bit?
The last two points are two ways of solving the “no port exposure” problem.
Both (3) and (4) would require you to build your SUT (System Under Test) in Docker. I assume this is a web service that listens on port 8080.
Item (3) suggests that you also include your tests and testing tools in the same image. This one really could be run with exec, since all you are doing is running the tests inside a running container (or docker run, if tests is the default action).
Image (4) suggests that you put your tests and testing tools in a different image to the SUT. This may be cleaner. What happens here is that you use a Docker network to connect the two containers (happens by default in Compose anyway) and they will be able to see each other without any ports needing to be exposed on the host.
image A: database image (not mine) listening on port 8080 and 28015
image B: message queue image (also not mine) listening on port 8080 and 6650
image C: my web service under test listens on another port, 10000, and has to connect to both image A and image B (on port 28015 and 6650 respectively)
(3) tests and testing tools in the same image - so I would have to “docker-compose” to get image A and image B, but in a different image just for tests?
(4) I think it would work - requires me to have a different configuration in tests that run in circleci/docker-compose to reach the right hosts (ie. use docker-compose DNS), but looks clean enough. Again, I don’t know how to signal that tests are done though.
You could set up Compose dependencies so your test image is spun up last, and then use --abort-on-container-exit for the up command, so that when your tests exit the whole thing is pulled down. You would have to check that you get zero/non-zero depending on suite pass/fail.
Alternatively, you could put a infinite while/sleep loop into your test image, and then run a docker exec from the outside to run the tests. This would be more reliable in terms of getting the right zero/non-zero job result.