From 72be139401224e6f553f7935b71ee75bc03e5abd Mon Sep 17 00:00:00 2001
From: Zoran Regvart <zoran@regvart.com>
Date: Wed, 4 Dec 2024 13:34:37 +0100
Subject: [PATCH] fix: container binds syntax (#2899)

The container binds syntax is `host-src:container-dest[:options]` or
`volume-name:container-dest[:options]` where `options` is a comma
separated list of: `nocopy` `[ro|rw]`, `[z|Z]` or
`[[r]shared|[r]slave|[r]private]`. See `HostConfig.Binds` of the Create
a container request[1]

[1] https://docs.docker.com/reference/api/engine/version/v1.47/#tag/Container/operation/ContainerCreate
---
 container.go      |  2 +-
 container_test.go | 26 ++++++++++++++++++++++++--
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/container.go b/container.go
index 90a7ba91cb..5ee0aac881 100644
--- a/container.go
+++ b/container.go
@@ -532,7 +532,7 @@ func (c *ContainerRequest) validateMounts() error {
 	if len(hostConfig.Binds) > 0 {
 		for _, bind := range hostConfig.Binds {
 			parts := strings.Split(bind, ":")
-			if len(parts) != 2 {
+			if len(parts) != 2 && len(parts) != 3 {
 				return fmt.Errorf("%w: %s", ErrInvalidBindMount, bind)
 			}
 			targetPath := parts[1]
diff --git a/container_test.go b/container_test.go
index c3581a379e..742a97436e 100644
--- a/container_test.go
+++ b/container_test.go
@@ -73,11 +73,33 @@ func Test_ContainerValidation(t *testing.T) {
 		},
 		{
 			Name:          "Invalid bind mount",
-			ExpectedError: "invalid bind mount: /data:/data:/data",
+			ExpectedError: "invalid bind mount: /data:/data:a:b",
 			ContainerRequest: testcontainers.ContainerRequest{
 				Image: "redis:latest",
 				HostConfigModifier: func(hc *container.HostConfig) {
-					hc.Binds = []string{"/data:/data:/data"}
+					hc.Binds = []string{"/data:/data:a:b"}
+				},
+			},
+		},
+		{
+			Name: "bind-options/provided",
+			ContainerRequest: testcontainers.ContainerRequest{
+				Image: "redis:latest",
+				HostConfigModifier: func(hc *container.HostConfig) {
+					hc.Binds = []string{
+						"/a:/a:nocopy",
+						"/b:/b:ro",
+						"/c:/c:rw",
+						"/d:/d:z",
+						"/e:/e:Z",
+						"/f:/f:shared",
+						"/g:/g:rshared",
+						"/h:/h:slave",
+						"/i:/i:rslave",
+						"/j:/j:private",
+						"/k:/k:rprivate",
+						"/l:/l:ro,z,shared",
+					}
 				},
 			},
 		},