diff --git a/dockertest.go b/dockertest.go index a2cc5c81..f4afb414 100644 --- a/dockertest.go +++ b/dockertest.go @@ -2,7 +2,9 @@ package dockertest import ( "fmt" + "io/ioutil" "os" + "path/filepath" "runtime" "strings" "time" @@ -133,6 +135,32 @@ type RunOptions struct { PortBindings map[dc.Port][]dc.PortBinding } +// BuildAndRunWithOptions builds and starts a docker container +func (d *Pool) BuildAndRunWithOptions(dockerfilePath string, opts *RunOptions) (*Resource, error) { + // Set the Dockerfile folder as build context + dir, file := filepath.Split(dockerfilePath) + + err := d.Client.BuildImage(dc.BuildImageOptions{ + Name: opts.Name, + Dockerfile: file, + OutputStream: ioutil.Discard, + ContextDir: dir, + }) + + if err != nil { + return nil, errors.Wrap(err, "") + } + + opts.Repository = opts.Name + + return d.RunWithOptions(opts) +} + +// BuildAndRun builds and starts a docker container +func (d *Pool) BuildAndRun(name, dockerfilePath string, env []string) (*Resource, error) { + return d.BuildAndRunWithOptions(dockerfilePath, &RunOptions{Name: name, Env: env}) +} + // RunWithOptions starts a docker container. // // pool.Run(&RunOptions{Repository: "mongo", Cmd: []string{"mongod", "--smallfiles"}}) diff --git a/dockertest_test.go b/dockertest_test.go index 7b056c5b..5b1a25c5 100644 --- a/dockertest_test.go +++ b/dockertest_test.go @@ -3,15 +3,16 @@ package dockertest import ( "database/sql" "fmt" + "io/ioutil" "log" "net/http" "os" "testing" + dc "github.com/fsouza/go-dockerclient" _ "github.com/lib/pq" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - dc "github.com/fsouza/go-dockerclient" ) var docker = os.Getenv("DOCKER_URL") @@ -77,12 +78,12 @@ func TestMongo(t *testing.T) { func TestContainerWithName(t *testing.T) { resource, err := pool.RunWithOptions( &RunOptions{ - Name: "db", + Name: "db", Repository: "postgres", - Tag: "9.5", + Tag: "9.5", }) require.Nil(t, err) - assert.Equal(t,"/db", resource.Container.Name) + assert.Equal(t, "/db", resource.Container.Name) require.Nil(t, pool.Purge(resource)) } @@ -91,13 +92,31 @@ func TestContainerWithPortBinding(t *testing.T) { resource, err := pool.RunWithOptions( &RunOptions{ Repository: "postgres", - Tag: "9.5", + Tag: "9.5", PortBindings: map[dc.Port][]dc.PortBinding{ "5432/tcp": {{HostIP: "", HostPort: "5433"}}, }, }) require.Nil(t, err) - assert.Equal(t,"5433", resource.GetPort("5432/tcp")) + assert.Equal(t, "5433", resource.GetPort("5432/tcp")) + + require.Nil(t, pool.Purge(resource)) +} + +func TestBuildImage(t *testing.T) { + // Create Dockerfile in temp dir + dir, _ := ioutil.TempDir("", "dockertest") + defer os.RemoveAll(dir) + + dockerfilePath := dir + "/Dockerfile" + ioutil.WriteFile(dockerfilePath, + []byte("FROM postgres:9.5"), + 0644, + ) + + resource, err := pool.BuildAndRun("postgres-test", dockerfilePath, nil) + require.Nil(t, err) + assert.Equal(t, "/postgres-test", resource.Container.Name) require.Nil(t, pool.Purge(resource)) -} \ No newline at end of file +} diff --git a/examples/BuildDockerfile.md b/examples/BuildDockerfile.md new file mode 100644 index 00000000..43dc2be9 --- /dev/null +++ b/examples/BuildDockerfile.md @@ -0,0 +1,34 @@ +`./db/image/Dockerfile` +```Dockerfile +FROM postgres:latest + +# Add your customizations here +``` + +`./db_test.go` +```go +pool, err := dockertest.NewPool("") +if err != nil { + log.Fatalf("Could not connect to docker: %s", err) +} + +// Build and run the given Dockerfile +resource, err := pool.BuildAndRun("my-postgres-test-image", "./db/image/Dockerfile", []string{}) +if err != nil { + log.Fatalf("Could not start resource: %s", err) +} + +if err = pool.Retry(func() error { + var err error + db, err = sql.Open("postgres", fmt.Sprintf("postgres://postgres:secret@localhost:%s/%s?sslmode=disable", resource.GetPort("5432/tcp"), database)) + if err != nil { + return err + } + return db.Ping() +}); err != nil { + log.Fatalf("Could not connect to docker: %s", err) +} + +// When you're done, kill and remove the container +err = pool.Purge(resource) +``` \ No newline at end of file