{"id":20208903,"url":"https://github.com/palantir/docker-compose-rule","last_synced_at":"2025-05-16T08:03:54.660Z","repository":{"id":37493227,"uuid":"50542309","full_name":"palantir/docker-compose-rule","owner":"palantir","description":"A JUnit rule to manage docker containers using docker-compose","archived":false,"fork":false,"pushed_at":"2024-06-03T16:42:54.000Z","size":1923,"stargazers_count":424,"open_issues_count":80,"forks_count":91,"subscribers_count":261,"default_branch":"master","last_synced_at":"2024-06-21T20:08:24.307Z","etag":null,"topics":["docker","docker-compose","junit","junit-rule","junit4","octo-correct-managed"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/palantir.png","metadata":{"files":{"readme":"README.md","changelog":"changelog/0.36.1/pr-293.v2.yml","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-27T22:24:46.000Z","updated_at":"2024-03-31T14:17:21.000Z","dependencies_parsed_at":"2024-03-06T05:24:04.689Z","dependency_job_id":"7d5954e4-beab-4ca4-9362-84ef56bc956e","html_url":"https://github.com/palantir/docker-compose-rule","commit_stats":null,"previous_names":[],"tags_count":86,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/palantir%2Fdocker-compose-rule","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/palantir%2Fdocker-compose-rule/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/palantir%2Fdocker-compose-rule/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/palantir%2Fdocker-compose-rule/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/palantir","download_url":"https://codeload.github.com/palantir/docker-compose-rule/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254493380,"owners_count":22080126,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","junit","junit-rule","junit4","octo-correct-managed"],"created_at":"2024-11-14T05:37:58.993Z","updated_at":"2025-05-16T08:03:54.643Z","avatar_url":"https://github.com/palantir.png","language":"Java","funding_links":[],"categories":["测试"],"sub_categories":[],"readme":"\u003cp align=\"right\"\u003e\n\u003ca href=\"https://autorelease.general.dmz.palantir.tech/palantir/docker-compose-rule\"\u003e\u003cimg src=\"https://img.shields.io/badge/Perform%20an-Autorelease-success.svg\" alt=\"Autorelease\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n[![build status](https://circleci.com/gh/palantir/docker-compose-rule.svg?style=shield\u0026circle-token=ed5bbc06f483e3f7324d1b3440125827c8d355d7)](https://circleci.com/gh/palantir/docker-compose-rule) [ ![Download](https://api.bintray.com/packages/palantir/releases/docker-compose-rule/images/download.svg) ](https://bintray.com/palantir/releases/docker-compose-rule/_latestVersion)\n\nDocker Compose JUnit Rule\n=========================\n\nThis is a library for executing JUnit tests that interact with Docker Compose managed containers. It supports the following:\n\n- Starting containers defined in a docker-compose.yml before tests and tearing them down afterwards\n- Waiting for services to become available before running tests\n- Recording log files from containers to aid debugging test failures\n\nWhy should I use this?\n----------------------\n\nThe code here started out as the end to end tests for one of our products. We needed to test this product in a variety of different configurations and environments which were mutually incompatible, thus multiple Docker Compose files were needed and so a simplistic model of running `docker-compose up` in Gradle was insufficient.\n\nIf you're experiencing any of the following using Docker for your testing this library should hopefully help:\n\n- Orchestrating multiple services and mapping the ports to outside the Docker machine so assertions can be made in tests\n- Needing to know when services are up to prevent flickering tests caused by slow to start services or complicated service dependencies\n- Lack of insight into what has happened in Docker containers during tests on CI servers due to loss of logs\n- Tests failing due to needing open ports on the CI build host which conflict with the test configuration\n\nSimple Use\n----------\n\nAdd a dependency to your project. For example, in gradle:\n\n```groovy\nrepositories {\n    maven {\n        url 'https://dl.bintray.com/palantir/releases' // docker-compose-rule is published on bintray\n    }\n}\ndependencies {\n    testCompile 'com.palantir.docker.compose:docker-compose-rule-junit4:\u003clatest-tag-from-bintray\u003e'\n}\n```\n\nFor the most basic use simply add a `DockerComposeRule` object as a `@ClassRule` or `@Rule` in a JUnit test class.\n\n```java\npublic class MyIntegrationTest {\n\n    @ClassRule\n    public static DockerComposeRule docker = DockerComposeRule.builder()\n            .file(\"src/test/resources/docker-compose.yml\")\n            .build();\n\n    @Test\n    public void testThatUsesSomeDockerServices() throws InterruptedException, IOException {\n       ...\n    }\n\n}\n```\n\nThis will cause the containers defined in `src/test/resources/docker-compose.yml` to be started by Docker Compose before the test executes and then the containers will be killed and removed (along with associated volumes) once the test has finished executing. If the containers have healthchecks specified, either [in the docker image](https://docs.docker.com/engine/reference/builder/#/healthcheck) or [in the docker-compose config](https://docs.docker.com/compose/compose-file/#/healthcheck), the test will wait for them to become healthy.\n\nThe `docker-compose.yml` file is referenced using the path given, relative to the working directory of the test. It will not be copied elsewhere and so references to shared directories and other resources for your containers can be made using path relative to this file as normal. If you wish to manually run the Docker containers for debugging the tests simply run `docker-compose up` in the same directory as the `docker-compose.yml`.\n\n### JUnit 5\n\nIf you'd prefer to use JUnit 5 (aka JUnit Jupiter), use the following dependency and replace your usages of `DockerComposeRule` with `DockerComposeExtension`.\n\n```gradle\ndependencies {\n    testCompile 'com.palantir.docker.compose:docker-compose-junit-jupiter:\u003clatest-tag-from-bintray\u003e'\n}\n```\n\n```java\npublic class MyIntegrationTest {\n\n    @RegisterExtension\n    public static DockerComposeExtension docker = DockerComposeExtension.builder()\n            .file(\"src/test/resources/docker-compose.yml\")\n            .build();\n\n    @Test\n    public void testThatUsesSomeDockerServices() throws InterruptedException, IOException {\n       ...\n    }\n\n}\n```\n\n### Running on a Mac\n\nThe above example will work out of the box on Linux machines with Docker installed. On Mac you will first need to install Docker using the instructions [here](https://docs.docker.com/v1.8/installation/mac/).\n\nOnce Docker is installed to run from the command line you will need to execute `docker-machine env \u003cmachine_name\u003e` and follow the instructions to set the environment variables. Any tests can now be executed through Gradle in the usual way.\n\nTo run the tests from your IDE you will need to add the environment variables given from running `docker-machine env \u003cmachine_name\u003e` to the run configuration for the test in your IDE. This is documented for [Eclipse](http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftasks-java-local-configuration.htm) and [IntelliJ](https://www.jetbrains.com/idea/help/run-debug-configuration-application.html).\n\nWaiting for a service to be available\n-------------------------------------\n\nTo wait for services to be available before executing tests, either add health checks to the configuration, or use the following methods on the `DockerComposeRule` object:\n\n```java\npublic class MyEndToEndTest {\n\n    @ClassRule\n    public static DockerComposeRule docker = DockerComposeRule.builder()\n        .file(\"src/test/resources/docker-compose.yml\")\n        .waitingForService(\"db\", HealthChecks.toHaveAllPortsOpen())\n        .waitingForService(\"web\", HealthChecks.toRespondOverHttp(8080, (port) -\u003e port.inFormat(\"https://$HOST:$EXTERNAL_PORT\")))\n        .waitingForService(\"other\", container -\u003e customServiceCheck(container), Duration.standardMinutes(2))\n        .waitingForServices(ImmutableList.of(\"node1\", \"node2\"), toBeHealthyAsACluster())\n        .waitingForHostNetworkedPort(5432, toBeOpen())\n        .build();\n\n    @Test\n    public void testThatDependsServicesHavingStarted() throws InterruptedException, IOException {\n        ...\n    }\n}\n```\n\nThe entrypoint method `waitingForService(String container, HealthCheck\u003cContainer\u003e check[, Duration timeout])` will make sure the healthcheck passes for that container before the tests start.\nThe entrypoint method `waitingForServices(List\u003cString\u003e containers, HealthCheck\u003cList\u003cContainer\u003e\u003e check[, Duration timeout])` will make sure the healthcheck passes for the cluster of containers before the tests start.\nThe entrypoint method `waitingForHostNetworkedPort(int portNumber, HealthCheck\u003cDockerPort\u003e check[, Duration timeout])` will make sure the healthcheck passes for a particular host networked port.\n\nWe provide 2 default healthChecks in the HealthChecks class:\n\n1. `toHaveAllPortsOpen` - this waits till all ports can be connected to that are exposed on the container\n2. `toRespondOverHttp` - which waits till the specified URL responds to a HTTP request.\n\nAccessing services in containers from outside a container\n---------------------------------------------------------\n\nIn tests it is likely services inside containers will need to be accessed in order to assert that they are behaving correctly. In addition, when tests run on Mac the Docker containers will be inside a Virtual Box machine and so must be accessed on an external IP address rather than the loopback interface.\n\nIt is recommended to only specify internal ports in the `docker-compose.yml` as described in the (reference)[https://docs.docker.com/compose/compose-file/#ports]. This makes tests independent of the environment on the host machine and of each other.  Docker will then randomly allocate an external port. For example:\n\n```yaml\npostgres:\n  image: postgres:9.5\n  ports:\n    - 5432\n```\n\nGiven a `DockerComposeRule` instance called `docker`, you could then access a service called\n`postgres` as follows\n\n```java\nDockerPort postgres = docker.containers()\n        .container(\"postgres\")\n        .port(5432);\n```\n\nYou could then interpolate the host IP address and random external port as follows:\n\n```java\nString url = postgres.inFormat(\"jdbc:postgresql://$HOST:$EXTERNAL_PORT/mydb\");\n// e.g. \"jdbc:postgresql://192.168.99.100:33045/mydb\"\n```\n\nRun docker-compose exec\n---------------------------------------------------------\n\nWe support docker-compose exec command which runs a new command in a running container.\n\n\n```java\ndockerCompose.exec(dockerComposeExecOption, containerName, dockerComposeExecArgument)\n```\n\nJust be aware that you need at least docker-compose 1.7 to run docker-compose exec\n\n\nCollecting logs\n---------------\n\nTo record the logs from your containers specify a location:\n\n```java\npublic class DockerComposeRuleTest {\n\n    @ClassRule\n    public static DockerComposeRule docker = DockerComposeRule.builder()\n            .file(\"src/test/resources/docker-compose.yml\")\n            .saveLogsTo(\"build/dockerLogs/dockerComposeRuleTest\")\n            .build();\n\n    @Test\n    public void testRecordsLogs() throws InterruptedException, IOException {\n       ...\n    }\n\n}\n```\n\nThis will collect logs for all containers. Collection will occur when after the tests are finished executing.\n\nThe `LogDirectory` class contains utility methods to generate these paths.  For example, you can write logs directly into the `$CIRCLE_ARTIFACTS` directory on CI (but fall back to `build/dockerLogs` locally) using:\n\n```java\n    .saveLogsTo(circleAwareLogDirectory(MyTest.class))\n```\n\nMethods in `LogDirectory` are intended to be statically imported for readability.\n\nSkipping shutdown\n-----------------\n\nTo skip shutdown of containers after tests are finished executing:\n\n```java\npublic class DockerComposeRuleTest {\n    @ClassRule\n    public static DockerComposeRule docker = DockerComposeRule.builder()\n            .file(\"src/test/resources/docker-compose.yml\")\n            .skipShutdown(true)\n            .build();\n}\n```\n\nThis can shorten iteration time when services take a long time to start. Remember to never leave it on in CI!\n\nPull images on startup\n-----------------\n\nTo pull images before starting the containers:\n\n```java\npublic class DockerCompositionTest {\n    @ClassRule\n    public static DockerComposition composition = DockerComposition.of(\"src/test/resources/docker-compose.yml\")\n                                                .pullOnStartup(true)\n                                                .build();\n}\n```\n\nThis will make sure you are using the most up-to-date version of all the images included in the docker-compose.yml.\n\nDocker Machine\n--------------\n\nDocker is able to connect to daemons that either live on the machine where the client is running, or somewhere remote.\nUsing the `docker` client, you are able to control which daemon to connect to using the `DOCKER_HOST` environment\nvariable.\n\n### Local Machine\n\nThe default out-of-the-box behaviour will configure `docker-compose` to connect to a Docker daemon that is running\n*locally*. That is, if you're on Linux, it will use the Docker daemon that exposes its socket. In the case of Mac OS X -\nwhich doesn't support Docker natively - we have to connect to a technically \"remote\" (but local) Docker daemon which is\nrunning in a virtual machine via `docker-machine`.\n\nIf you're on Mac OS X, the `docker` cli expects the following environment variables:\n\n - `DOCKER_HOST`\n - If the Docker daemon is secured by TLS, `DOCKER_TLS_VERIFY` and `DOCKER_CERT_PATH` need to be set.\n\nSimilarly, if you're using a `LocalMachine`, you need to ensure the Run Configuration (in your IDE, command line etc.)\nhas those same variables set.\n\nAn example of creating a `DockerMachine` that connects to a local docker daemon:\n\n```java\nDockerMachine.localMachine()\n             .build()\n```\n\n### Remote Machine\n\nYou may not always want to connect to a Docker daemon that is running on your local computer or a virtual machine\nrunning on your local computer.\n\nAn example of this would be running containers in a clustered manner with Docker Swarm. Since Docker Swarm implements\nthe Docker API, setting the right environment variables would allow us to use Docker containers on the swarm.\n\nAn example of connecting to a remote Docker daemon that has also been secured by TLS:\n\n```java\nDockerMachine.remoteMachine()\n             .host(\"tcp://remote-docker-host:2376\")\n             .withTLS(\"/path/to/cert\")\n             .build()\n```\n\n### Additional Environment Variables\n\nIt may also be useful to pass environment variables to the process that will call `docker-compose`.\n\nYou can do so in the following manner:\n\n```java\nDockerMachine.localMachine()\n             .withEnvironmentVariable(\"SOME_VARIABLE\", \"SOME_VALUE\")\n             .build()\n```\n\nThe variable `SOME_VARIABLE` will be available in the process that calls `docker-compose`, and can be used for Variable Interpolation inside the compose file.\n\n### How to use a `DockerMachine`\n\nWhen creating a `DockerComposeRule`, a custom `DockerMachine` may be specified. If no `DockerMachine` is specified, `DockerComposeRule` will connect to the local Docker\ndaemon, similarly to how the `docker` cli works.\n\n```java\nprivate final DockerMachine dockerMachine = DockerMachine.localMachine()\n                                                         .withAdditionalEnvironmentVariable(\"SOME_VARIABLE\", \"SOME_VALUE\")\n                                                         .build();\n\n@Rule\nDockerComposeRule docker = DockerComposeRule.builder()\n            .file(\"docker-compose.yaml\")\n            .machine(dockerMachine)\n            .build();\n```\n\nComposing docker compose files\n------------------------------\n\n`docker-compose` (at least as of version 1.5.0) allows us to specify multiple docker-compose files. On the command line, you\ncan do this with this example command:\n\n    docker-compose -f file1.yml -f file2.yml -f file3.yml\n\nSemantics of how this works is explained here: [Docker compose reference](https://docs.docker.com/compose/reference/overview/)\n\nTo use this functionality inside docker-compose-rule, supply a `DockerComposeFiles` object to your `DockerComposeRule` builder:\n\n```java\nDockerComposeRule docker = DockerComposeRule.builder()\n            .files(DockerComposeFiles.from(\"file1.yml\", \"file2.yml\"))\n            .build()\n```\n\nUsing a custom version of docker-compose\n---------------\n\ndocker-compose-rule tries to use the docker-compose binary located at `/usr/local/bin/docker-compose`. This can be overriden by setting `DOCKER_COMPOSE_LOCATION` to be the path to a valid file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpalantir%2Fdocker-compose-rule","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpalantir%2Fdocker-compose-rule","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpalantir%2Fdocker-compose-rule/lists"}