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

Support custom Docker images in the JDBC URL #4

Open
swissarmykirpan opened this issue Apr 29, 2015 · 21 comments
Open

Support custom Docker images in the JDBC URL #4

swissarmykirpan opened this issue Apr 29, 2015 · 21 comments
Milestone

Comments

@swissarmykirpan
Copy link
Member

Make it possible to specify a full docker image name in the JDBC URL and/or custom docker registries, and these might be necessary to allow teams to use their own privately managed images.

@rnorth
Copy link
Member

rnorth commented Apr 30, 2015

I was looking into this yesterday - would be keen to get your thoughts and the ideas from folks in your team.

Right now, I think if you have a custom container class with image name of the form hostname:port/image:tag then docker will be able to pull from a private registry (assuming the user has already authenticated). This seems like a nice zero-effort solution to me, though I need to test it actually works.

An alternative would be a way to provide private registry hostname/credentials in some way, but this either needs to be encoded in the JDBC URL (getting busy) or as environment variables (less discoverable; requires more documentation).

What do you think?

@rnorth
Copy link
Member

rnorth commented Apr 30, 2015

@outofcoffee, @haines, any thoughts?

@haines
Copy link
Contributor

haines commented May 1, 2015

I think adding more JDBC URL query string parameters is ok for private registry hostname/credentials.

@swissarmykirpan
Copy link
Member Author

I guess it depends on where the private registry is and how they implement authentication. I know with docker, you can authenticate via the command line:

docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS

Then you can docker push or pull

@rnorth
Copy link
Member

rnorth commented Jun 26, 2015

I think this is sufficiently complex that we should leave it for a little
while and prioritise other things first.

On Fri, Jun 26, 2015 at 9:17 AM, gusohal notifications@github.com wrote:

I guess it depends on where the private registry is and how they implement
authentication. I know with docker, you can authenticate via the command
line:

docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS

Then you can docker push or pull


Reply to this email directly or view it on GitHub
#4 (comment)
.

@outofcoffee
Copy link
Contributor

Would like to see if @rnorth's suggestion works - if so, this seems like a sensible (and standard AFA Docker syntax is concerned) solution.

@rnorth
Copy link
Member

rnorth commented Jul 19, 2015

We need to try this out - sometime soon!

@rnorth
Copy link
Member

rnorth commented Feb 29, 2016

This may need further work before it is ready, see #70:

Thank you very much for the fix. Unfortunately it does seem to break support for local registries.
If I understand #4 correctly, the current proposed solution for using custom local image registries is to specify the image name like this: registryHost:port/imageName.
If I specify something like localhost:5000/my-image as image name, the build repeatedly pulls the image (similar behaviour as posted by buckett).
If I use localhost:5000/my-image:latest it says "No image tag was specified in docker image name etc.".

@rnorth rnorth added this to the 1.0.3 milestone Mar 31, 2016
@rnorth
Copy link
Member

rnorth commented Mar 31, 2016

This is now implemented - see #99

@rnorth rnorth closed this as completed Mar 31, 2016
@bsideup bsideup changed the title Pulling Docker images from private/custom docker registry Support custom Docker images in the JDBC URL Jan 24, 2020
@bsideup bsideup reopened this Jan 24, 2020
@bsideup
Copy link
Member

bsideup commented Jan 24, 2020

I re-opened the issue (4th issue of the project!) since it was talking about using custom images in the JDBC URL and it is still not implemented :D

@bsideup
Copy link
Member

bsideup commented Jan 24, 2020

Context

Example URL: jdbc:tc:mysql:5.6.23:///databasename
Here mysql is the driver's name, and :5.6.23 is a tag of mysql official image.

Problem 1

We cannot easily change it to jdbc:tc:custom-mysql:5.6.23:///databasename because then it will fail to resolve custom-mysql driver.

Problem 2

Custom registries (e.g. registry.my.corp:5000/foo/custom-mysql) are hard to encode in the URL.

Idea

de-couple the driver & image and introduce aliases:

// Must be called before using the URL
JdbcContainer.registerAlias("corporate-mysql", "mysql", "registry.my.corp:5000/foo/custom-mysql");

// And then start it with:
String jdbcUrl = "jdbc:tc:corporate-mysql:5.6.23:///databasename";

Where:

public static void registerAlias(String aliasName, String driverId, String imageName);

We could also add it to testcontainers.properties for those who don't want to use static methods

cc @rnorth @kiview

@SaschaJohn
Copy link

I had a discussion with @bsideup in Slack about this because I just recognized that testcontainers.properties are not considered for mysql module, while I was trying to overwrite mysql.container.image = mysql:8.0.19

IMHO aliases are a possibility, but I'm not sure if it's necessary.
Currently only few drivers are supported overwriting the images in testcontainers.properties is the current behavior in testcontainers.
Therefore it would also be possible to keep the coupling between driver and image and only need a custom image for a specific driver if necessary.

@rnorth
Copy link
Member

rnorth commented Jan 24, 2020

I think I like @bsideup's suggestion. I suspect that configuring via testcontainers.properties is definitely needed as a lowest common denominator, because it's sometimes hard for people to invoke a static method either early enough or even in the right JVM process.

But having the static method to register aliases offers some power too - it means that it's possible to look up an image using custom code, or even build one on the fly with ImageFromDockerfile.

@SaschaJohn
Copy link

SaschaJohn commented Jan 26, 2020

@rnorth , @bsideup
Feature is ready so far, was faster than expected :)
see: SaschaJohn@bb16527
Have to do a little cleanup, provide some tests and documentation as well

Code approach:
ContainerDatabaseDriver.registerAlias("mysqlserver", "sqlserver", "mcmoe/mssqldocker", "latest");
ContainerDatabaseDriver.registerAlias("myownmysql", "mysql", "mysql");

testcontainers.properties:
jdbc.alias.mysqlserver.type=sqlserver
jdbc.alias.mysqlserver.image=mcmoe/mssqldocker
jdbc.alias.mysqlserver.tag=latest

@binkley
Copy link

binkley commented Jan 30, 2020

@SaschaJohn Very glad to see your commit. I just stumbled on this issue yesterday when I tried using a custom postgres image which includes the tableversion extension.

Is there a way for me to try "nightly" builds? I'd like to try this out, and provide feedback.

@bsideup
Copy link
Member

bsideup commented Jan 30, 2020

@binkley the PR is not merged yet, but you can use http://jitpack.io to obtain a version of that code to test it without having to compile/install it yourself, just use PR2294-SNAPSHOT as version.

More info here:
https://www.testcontainers.org/jitpack_dependencies/

binkley added a commit to binkley/domain-persistence-modeling that referenced this issue Jan 30, 2020
See testcontainers/testcontainers-java#4 for
in-progress solution to custom images with JDBC.
@SaschaJohn
Copy link

@binkley looking forward for feedback :)

@binkley
Copy link

binkley commented Feb 4, 2020

@SaschaJohn Sorry for the slow reply. I've been struggling getting the dependencies working.

  1. The testcontainers documentation for jitpack is incorrect (contrast with the instructions on the jitpack site)
  2. I am unable to update all testcontainer dependencies to the same PR version; I got funky errors when only adding the testcontainers-java dep, and leaving junit-jupiter and postgresql deps at version 12.5

Since I still see "java.lang.IllegalArgumentException: JDBC URL matches jdbc:tc: prefix but the database or tag name could not be identified", it looks like I'm not using your PR branch version of testcontainers-java, but it's plain in pom.xml that it's the first testcontainers dependency listed.

I'm still poking at it.

bsideup added a commit that referenced this issue Apr 12, 2020
This PR adds support for [R2DBC](https://r2dbc.io).

## URL support

The URL support is similar to the JDBC's, but:

1. Does not reuse containers by URL - it is unclear yet how to "hash" `ConnectionFactoryOptions`
1. The image tag must be explicitly provided via `TC_IMAGE_TAG` r2dbc option
1. TODO: daemon mode
1. TODO: alias support (see #4)

## Example usage

The user **must add the `org.testcontainers:r2dbc` module** - unlike JDBC, we use `compileOnly` dependency on R2DBC, since it is a 3rd party dependency.

Once both the `r2dbc` and database's module are added, one can use:
```java
String url = "r2dbc:tc:postgresql:///db?TC_IMAGE_TAG=10-alpine";
ConnectionFactory connectionFactory = ConnectionFactories.get(url);
```

## Programmatic access

For those who start containers manually and want to obtain `ConnectionFactoryOptions` for already started containers, we provide a helper static method:
```java
try (PostgreSQLContainer<?> container = new PostgreSQLContainer<>()) {
    container.start();

    ConnectionFactory connectionFactory = ConnectionFactories.get(
        PostgreSQLR2DBCDatabaseContainer.getOptions(container)
    );
}
```
quincy referenced this issue in quincy/testcontainers-java May 28, 2020
This PR adds support for [R2DBC](https://r2dbc.io).

## URL support

The URL support is similar to the JDBC's, but:

1. Does not reuse containers by URL - it is unclear yet how to "hash" `ConnectionFactoryOptions`
1. The image tag must be explicitly provided via `TC_IMAGE_TAG` r2dbc option
1. TODO: daemon mode
1. TODO: alias support (see #4)

## Example usage

The user **must add the `org.testcontainers:r2dbc` module** - unlike JDBC, we use `compileOnly` dependency on R2DBC, since it is a 3rd party dependency.

Once both the `r2dbc` and database's module are added, one can use:
```java
String url = "r2dbc:tc:postgresql:///db?TC_IMAGE_TAG=10-alpine";
ConnectionFactory connectionFactory = ConnectionFactories.get(url);
```

## Programmatic access

For those who start containers manually and want to obtain `ConnectionFactoryOptions` for already started containers, we provide a helper static method:
```java
try (PostgreSQLContainer<?> container = new PostgreSQLContainer<>()) {
    container.start();

    ConnectionFactory connectionFactory = ConnectionFactories.get(
        PostgreSQLR2DBCDatabaseContainer.getOptions(container)
    );
}
```
@jyrno
Copy link

jyrno commented Oct 6, 2020

This is how we solved it for postgres:
Added docker.registry.url=my.custom.registry to src/test/resources/testcontainers.properties
Extended testcontainers postgres container with external registry support that handles our custom postgresqlext db types:

package my.package.postgresext;

import org.apache.commons.lang3.StringUtils;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.TestcontainersConfiguration;

public class ExternalRegistryPostgreSQLContainer<SELF extends ExternalRegistryPostgreSQLContainer<SELF>> extends PostgreSQLContainer<SELF> {

    public ExternalRegistryPostgreSQLContainer(final String dockerImageName) {
        super(getRegistryUrl() + dockerImageName);
    }

    private static String getRegistryUrl() {
        String registryUrl = (String) TestcontainersConfiguration.getInstance().getProperties().get("docker.registry.url");
        if (StringUtils.isEmpty(registryUrl)) {
            return StringUtils.EMPTY;
        }
        return StringUtils.appendIfMissing(registryUrl, "/");
    }
}
package my.package.postgresext;

import org.testcontainers.containers.JdbcDatabaseContainer;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.containers.PostgreSQLContainerProvider;

public class ExternalRegistryPostgreSQLContainerProvider extends PostgreSQLContainerProvider {

    private static final String NAME = "postgresqlext";

    @Override
    public boolean supports(String databaseType) {
        return NAME.equals(databaseType);
    }

    @Override
    public JdbcDatabaseContainer newInstance(String tag) {
        return new ExternalRegistryPostgreSQLContainer(PostgreSQLContainer.IMAGE + ":" + tag);
    }

}

Added that container class to src\test\resources\META-INF\services\org.testcontainers.containers.JdbcDatabaseContainerProvider
my.package.ExternalRegistryPostgreSQLContainerProvider

And then just declare your DB url with postgresqlext: jdbc:tc:postgresqlext://localhost/testdb

@bsideup
Copy link
Member

bsideup commented Oct 6, 2020

@jyrno FYI something like that soon will be natively supported by Testcontainers. See #2599 for an example of how it is proposed to be done for R2DBC

@gmelekh
Copy link

gmelekh commented Jan 31, 2023

any updates so far regarding azure-sql-edge with MSSQLServerContainer ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants