[api/client] Fix build when context dir is symlink
| ... | ... |
@@ -302,6 +302,22 @@ func getDockerfileRelPath(givenContextDir, givenDockerfile string) (absContextDi |
| 302 | 302 |
return "", "", fmt.Errorf("unable to get absolute context directory: %v", err)
|
| 303 | 303 |
} |
| 304 | 304 |
|
| 305 |
+ // The context dir might be a symbolic link, so follow it to the actual |
|
| 306 |
+ // target directory. |
|
| 307 |
+ absContextDir, err = filepath.EvalSymlinks(absContextDir) |
|
| 308 |
+ if err != nil {
|
|
| 309 |
+ return "", "", fmt.Errorf("unable to evaluate symlinks in context path: %v", err)
|
|
| 310 |
+ } |
|
| 311 |
+ |
|
| 312 |
+ stat, err := os.Lstat(absContextDir) |
|
| 313 |
+ if err != nil {
|
|
| 314 |
+ return "", "", fmt.Errorf("unable to stat context directory %q: %v", absContextDir, err)
|
|
| 315 |
+ } |
|
| 316 |
+ |
|
| 317 |
+ if !stat.IsDir() {
|
|
| 318 |
+ return "", "", fmt.Errorf("context must be a directory: %s", absContextDir)
|
|
| 319 |
+ } |
|
| 320 |
+ |
|
| 305 | 321 |
absDockerfile := givenDockerfile |
| 306 | 322 |
if absDockerfile == "" {
|
| 307 | 323 |
// No -f/--file was specified so use the default relative to the |
| ... | ... |
@@ -5394,3 +5394,41 @@ func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) {
|
| 5394 | 5394 |
c.Fatalf("Unexpected output on trusted build with untrusted tag:\n%s", out)
|
| 5395 | 5395 |
} |
| 5396 | 5396 |
} |
| 5397 |
+ |
|
| 5398 |
+func (s *DockerTrustSuite) TestBuildContextDirIsSymlink(c *check.C) {
|
|
| 5399 |
+ tempDir, err := ioutil.TempDir("", "test-build-dir-is-symlink-")
|
|
| 5400 |
+ if err != nil {
|
|
| 5401 |
+ c.Fatal(err) |
|
| 5402 |
+ } |
|
| 5403 |
+ defer os.RemoveAll(tempDir) |
|
| 5404 |
+ |
|
| 5405 |
+ // Make a real context directory in this temp directory with a simple |
|
| 5406 |
+ // Dockerfile. |
|
| 5407 |
+ realContextDirname := filepath.Join(tempDir, "context") |
|
| 5408 |
+ if err := os.Mkdir(realContextDirname, os.FileMode(0755)); err != nil {
|
|
| 5409 |
+ c.Fatal(err) |
|
| 5410 |
+ } |
|
| 5411 |
+ |
|
| 5412 |
+ if err = ioutil.WriteFile( |
|
| 5413 |
+ filepath.Join(realContextDirname, "Dockerfile"), |
|
| 5414 |
+ []byte(` |
|
| 5415 |
+ FROM busybox |
|
| 5416 |
+ RUN echo hello world |
|
| 5417 |
+ `), |
|
| 5418 |
+ os.FileMode(0644), |
|
| 5419 |
+ ); err != nil {
|
|
| 5420 |
+ c.Fatal(err) |
|
| 5421 |
+ } |
|
| 5422 |
+ |
|
| 5423 |
+ // Make a symlink to the real context directory. |
|
| 5424 |
+ contextSymlinkName := filepath.Join(tempDir, "context_link") |
|
| 5425 |
+ if err := os.Symlink(realContextDirname, contextSymlinkName); err != nil {
|
|
| 5426 |
+ c.Fatal(err) |
|
| 5427 |
+ } |
|
| 5428 |
+ |
|
| 5429 |
+ // Executing the build with the symlink as the specified context should |
|
| 5430 |
+ // *not* fail. |
|
| 5431 |
+ if out, exitStatus := dockerCmd(c, "build", contextSymlinkName); exitStatus != 0 {
|
|
| 5432 |
+ c.Fatalf("build failed with exit status %d: %s", exitStatus, out)
|
|
| 5433 |
+ } |
|
| 5434 |
+} |