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

Dockerfile COPY instruction doesn't adhere to parser directive "escape" #47776

Open
SetTrend opened this issue Apr 30, 2024 · 2 comments
Open
Labels
area/builder/classic-builder Issues affecting the classic builder area/builder kind/bug Bugs are bugs. The cause may or may not be known at triage time so debugging may be needed. platform/windows status/0-triage version/26.0

Comments

@SetTrend
Copy link

SetTrend commented Apr 30, 2024

Description

According to Dockerfile reference documentation on escape parser directive:

The escape directive sets the character used to escape characters in a Dockerfile. If not specified, the default escape character is \.

The escape character is used both to escape characters in a line, and to escape a newline. This allows a Dockerfile instruction to span multiple lines. Note that regardless of whether the escape parser directive is included in a Dockerfile, escaping is not performed in a RUN command, except at the end of a line.

Setting the escape character to ` is especially useful on Windows, where \ is the directory path separator. ` is consistent with Windows PowerShell.


However, this doesn't work.


According to Go's filepath.Match() documentation:

On Windows, escaping is disabled. Instead, '\\' is treated as path separator.


So, escaping is also not performed in a COPY command.

Reproduce

Dockerfile

# escape=`
FROM mcr.microsoft.com/windows/servercore:20H2
COPY [ "\*", "C:\Temp\" ]
docker build --rm -t test:latest .

Expected behavior

The above Dockerfile build should flawlessly copy the whole context to the Windows container's C:\Temp\ directory.

Actual behavior

The COPY instruction fails.

Step 2/2 : COPY [ "\*.*", "C:\Temp\" ]
COPY failed: file not found in build context or excluded by .dockerignore: stat C:\Temp\: file does not exist

docker version

Client:
 Cloud integration: v1.0.35+desktop.13
 Version:           26.0.0
 API version:       1.45
 Go version:        go1.21.8
 Git commit:        2ae903e
 Built:             Wed Mar 20 15:18:56 2024
 OS/Arch:           windows/amd64
 Context:           default

Server: Docker Desktop 4.29.0 (145265)
 Engine:
  Version:          26.0.0
  API version:      1.45 (minimum version 1.24)
  Go version:       go1.21.8
  Git commit:       8b79278
  Built:            Wed Mar 20 15:17:49 2024
  OS/Arch:          windows/amd64
  Experimental:     false

docker info

Client:
 Version:    26.0.0
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.13.1-desktop.1
    Path:     C:\Program Files\Docker\cli-plugins\docker-buildx.exe
  compose: Docker Compose (Docker Inc.)
    Version:  v2.26.1-desktop.1
    Path:     C:\Program Files\Docker\cli-plugins\docker-compose.exe
  debug: Get a shell into any image or container. (Docker Inc.)
    Version:  0.0.27
    Path:     C:\Program Files\Docker\cli-plugins\docker-debug.exe
  dev: Docker Dev Environments (Docker Inc.)
    Version:  v0.1.2
    Path:     C:\Program Files\Docker\cli-plugins\docker-dev.exe
  extension: Manages Docker extensions (Docker Inc.)
    Version:  v0.2.23
    Path:     C:\Program Files\Docker\cli-plugins\docker-extension.exe
  feedback: Provide feedback, right in your terminal! (Docker Inc.)
    Version:  v1.0.4
    Path:     C:\Program Files\Docker\cli-plugins\docker-feedback.exe
  init: Creates Docker-related starter files for your project (Docker Inc.)
    Version:  v1.1.0
    Path:     C:\Program Files\Docker\cli-plugins\docker-init.exe
  sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc.)
    Version:  0.6.0
    Path:     C:\Program Files\Docker\cli-plugins\docker-sbom.exe
  scout: Docker Scout (Docker Inc.)
    Version:  v1.6.3
    Path:     C:\Program Files\Docker\cli-plugins\docker-scout.exe

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 9
 Server Version: 26.0.0
 Storage Driver: windowsfilter
  Windows:
 Logging Driver: json-file
 Plugins:
  Volume: local
  Network: ics internal l2bridge l2tunnel nat null overlay private transparent
  Log: awslogs etwlogs fluentd gcplogs gelf json-file local splunk syslog     
 Swarm: inactive
 Default Isolation: hyperv
 Kernel Version: 10.0 19045 (19041.1.amd64fre.vb_release.191206-1406)
 Operating System: Microsoft Windows Version 22H2 (OS Build 19045.4291)       
 OSType: windows
 Architecture: x86_64
 CPUs: 4
 Total Memory: 12GiB
 Name: ***
 ID: 10204c76-f9b4-45e9-ba1d-7c6093465950
 Docker Root Dir: C:\ProgramData\Docker
 Debug Mode: false
 Labels:
  com.docker.desktop.address=npipe://\\.\pipe\docker_cli
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
 Product License: Community Engine
@SetTrend SetTrend added kind/bug Bugs are bugs. The cause may or may not be known at triage time so debugging may be needed. status/0-triage labels Apr 30, 2024
@thaJeztah
Copy link
Member

I'm not on a Windows machine myself (but could ask someone to try); I wonder here if it's failing to parse the JSON (COPY accepts both positional arguments or a JSON-array); for this, it first tries to detect if its a valid JSON array (which it isn't due to the escaped \"), otherwise it's treated as a literal (COPY [<src> ...] <dest>, which in this case may be copy [, "\*.*",, "C:\Temp\" to ] (<dest>)); 🤔

COPY [ "\*.*", "C:\Temp\" ]

@SetTrend
Copy link
Author

SetTrend commented Apr 30, 2024

I just tested it. You are right: When omitting the brackets the script is working:

Step 2/2 : COPY "\LocalLayout\" "C:\Temp\"
 ---> 951b3068c13b
Successfully built 951b3068c13b

Yet, the problem still remains: At this time, the documentation on COPY is rather sparse and unclear:

COPY has two forms. The latter form is required for paths containing whitespace.

[COPY](https://docs.docker.com/reference/dockerfile/#copy) [OPTIONS] <src> ... <dest>
[COPY](https://docs.docker.com/reference/dockerfile/#copy) [OPTIONS] ["<src>", ... "<dest>"]

If all the corner cases would need to be documented, the documentation would read like:

COPY has a plethora of forms:

[COPY](https://docs.docker.com/reference/dockerfile/#copy) [OPTIONS] <src> ... <dest>

The following forms are required for paths containing whitespace:

[COPY](https://docs.docker.com/reference/dockerfile/#copy) [OPTIONS] "<src>" ... "<dest>"
[COPY](https://docs.docker.com/reference/dockerfile/#copy) [OPTIONS] ["<src>", ... "<dest>"]

The escape parser directive character is not adhered to when using the last form, which is a JSON array.


I propose to have the Dockerfile parser perform an initial simple text replacement first if an escape parser directive exists. The Docker engine code would then be like this (I'm using pseudo code here as I'm not acquainted with the Go programming language):

string dockerFile = ReadDockerfile()
char escape = /#\s*escape\s*=\s*(.+)/.match(dockerFile)

if (escape != '' && escape != '\\') dockerFile = dockerFile.Replace('\\', '\\\\').Replace(escape, '\\')

Otherwise, the escape parser directive wouldn't make any sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/builder/classic-builder Issues affecting the classic builder area/builder kind/bug Bugs are bugs. The cause may or may not be known at triage time so debugging may be needed. platform/windows status/0-triage version/26.0
Projects
None yet
Development

No branches or pull requests

3 participants
@thaJeztah @SetTrend and others