diff --git a/docs/sources/reference/builder.rst b/docs/sources/reference/builder.rst index 0d8d750a04..1c8331e98f 100644 --- a/docs/sources/reference/builder.rst +++ b/docs/sources/reference/builder.rst @@ -407,7 +407,16 @@ the image. The ``WORKDIR`` instruction sets the working directory for the ``RUN``, ``CMD`` and ``ENTRYPOINT`` Dockerfile commands that follow it. -It can be used multiple times in the one Dockerfile. +It can be used multiple times in the one Dockerfile. If a relative path is +provided, it will be relative to the path of the previous ``WORKDIR`` +instruction. For example: + + WORKDIR /a + WORKDIR b + WORKDIR c + RUN pwd + +The output of the final ``pwd`` command in this Dockerfile would be ``/a/b/c``. 3.11 ONBUILD ------------ diff --git a/integration/buildfile_test.go b/integration/buildfile_test.go index 7f6e69ece3..95d5abb8a7 100644 --- a/integration/buildfile_test.go +++ b/integration/buildfile_test.go @@ -441,6 +441,25 @@ func TestBuildUser(t *testing.T) { } } +func TestBuildRelativeWorkdir(t *testing.T) { + img, err := buildImage(testContextTemplate{` + FROM {IMAGE} + RUN [ "$PWD" = '/' ] + WORKDIR test1 + RUN [ "$PWD" = '/test1' ] + WORKDIR /test2 + RUN [ "$PWD" = '/test2' ] + WORKDIR test3 + RUN [ "$PWD" = '/test2/test3' ] + `, nil, nil}, t, nil, true) + if err != nil { + t.Fatal(err) + } + if img.Config.WorkingDir != "/test2/test3" { + t.Fatalf("Expected workdir to be '/test2/test3', received '%s'", img.Config.WorkingDir) + } +} + func TestBuildEnv(t *testing.T) { img, err := buildImage(testContextTemplate{` from {IMAGE} diff --git a/server/buildfile.go b/server/buildfile.go index af6702cc1d..5d5fda4d8e 100644 --- a/server/buildfile.go +++ b/server/buildfile.go @@ -338,7 +338,14 @@ func (b *buildFile) CmdCopy(args string) error { } func (b *buildFile) CmdWorkdir(workdir string) error { - b.config.WorkingDir = workdir + if workdir[0] == '/' { + b.config.WorkingDir = workdir + } else { + if b.config.WorkingDir == "" { + b.config.WorkingDir = "/" + } + b.config.WorkingDir = filepath.Join(b.config.WorkingDir, workdir) + } return b.commit("", b.config.Cmd, fmt.Sprintf("WORKDIR %v", workdir)) }