Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it work with a remote docker host #89

Closed
thomaseizinger opened this issue May 9, 2019 · 4 comments · Fixed by #575
Closed

Make it work with a remote docker host #89

thomaseizinger opened this issue May 9, 2019 · 4 comments · Fixed by #575

Comments

@thomaseizinger
Copy link
Collaborator

The docker daemon can be hosted on a remote machine, hence in addition to the port of a container, we should also expose the host on which the docker container was started.

@mchlstckl
Copy link

I ran into this issue on Gitlab CI where you need to set the DOCKER_HOST=tcp://docker:2375.

I ended up writing an extension trait that extends Container with a get_host() method. The method url parses the DOCKER_HOST value and if scheme is ”tcp” returns the url host else returns ”localhost” (like when the scheme is ”unix”).

@0xFFFFFFFFFFFFFFFFFF
Copy link

I ran into this issue on Gitlab CI where you need to set the DOCKER_HOST=tcp://docker:2375.

I ended up writing an extension trait that extends Container with a get_host() method. The method url parses the DOCKER_HOST value and if scheme is ”tcp” returns the url host else returns ”localhost” (like when the scheme is ”unix”).

@mchlstckl Could you please provide us some snippets of the relevant lines including the .gitlab-ci.yml? My integration tests are running fine on my local machines but not in the GitLab runner. I was struggling the past days to get this working, but I haven't figured out yet.

@mchlstckl
Copy link

mchlstckl commented Mar 15, 2023 via email

@0xFFFFFFFFFFFFFFFFFF
Copy link

No problem, thanks for checking though. I managed to get it working and want to share it in case someone else stumbles on on this.
I am passing my docker socket to the runner as described here.

.gitlab-ci.yml:

test:
  image: rust:1
  stage: test
  before_script:
    - wget https://download.docker.com/linux/static/stable/x86_64/docker-23.0.1.tgz
    - tar xvfz docker-23.0.1.tgz
    - mv docker/docker /usr/bin/
    - rm -Rf docker/ docker-23.0.1.tgz
  script:
    - cargo test

rust trait:

use std::{process::Command, io::Read, str::FromStr};

pub trait ContainerHost {
  fn get_host_addr(&self) -> String;
}

impl<'d, I> ContainerHost for testcontainers::Container<'d, I>
where
    I: testcontainers::Image,
{
    fn get_host_addr(&self) -> String {
      let mut output = String::new();
      Command::new("docker")
      .arg("inspect")
      .arg("-f")
      .arg("'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'")
      .arg(&self.id())
      .output()
      .expect("inspecting container")
      .stdout
      .as_slice()
      .read_to_string(&mut output)
      .expect("parsing IP address");
      let output = output.replace('\'', "");
      let output = String::from(output.trim());

      assert!(std::net::IpAddr::from_str(output.as_str()).is_ok());
      output
    }
}

Then you can just connect to the container using its IP and internal port in your integration test.

github-merge-queue bot pushed a commit that referenced this issue Apr 22, 2024
Quite large refactoring as part of project revamp #563, and also the
long-awaited refactoring #386

Now it's really simple API, e.g:
```rs
let container = GenericImage::new("redis", "latest")
        .with_exposed_port(6379)
        .with_wait_for(WaitFor::message_on_stdout("Ready to accept connections"))
        .start();
```

I find this new API much easier to use, solves a lot of problems, and
seems flexible enough to be extended.
This also works regardless of the tokio runtime flavor (multi-thread vs
current-thread). And the sync API is still available, right under
`blocking` feature (just like `reqwest` does).

From a maintainer's perspective this also simplifies the code, we don't
have to worry about two different clients and their differences.

### Docker host resolution
The host is resolved in the following order:

1. Docker host from the `tc.host` property in the
`~/.testcontainers.properties` file.
2. `DOCKER_HOST` environment variable.
3. Docker host from the "docker.host" property in the
`~/.testcontainers.properties` file.
4. Else, the default Docker socket will be returned.

### Notes
- MSRV was bumped to `1.70` in order to use `std::sync::OnceLock`. This
should NOT be a problem, tests usually executed on more recent versions
(also see [this
ref](https://github.com/testcontainers/testcontainers-rs/pull/503/files#r1242651354)).
- `Cli` client is removed, instead we provide `sync` (under `blocking`
feature) and `async` impls based on HTTP client (bollard)
- tested with
[modules](https://github.com/testcontainers/testcontainers-rs-modules-community)

## Migration guide 

- Sync API migration (`Cli` client)
  - Add `blocking` feature
  - Drop all usages of `clients::Cli`
  - Add `use testcontainers::runners::SyncRunner;`
  - Replace `client.run(image)` with `image.start()`
- Async API migration (`Http` client)
  - Remove `experimental` feature
  - Drop all usages of `clients::Http`
  - Add `use testcontainers::runners::AsyncRunner;`
  - Replace `client.run(image)` with `image.start()`

## References

Closes #386
Closes #326
Closes #475
Closes #508
Closes #392
Closes #561
Closes #559
Closes #564
Closes #538
Closes #507
Closes #89
Closes #198
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants