1# escape=`
2
3# -----------------------------------------------------------------------------------------
4# This file describes the standard way to build Docker in a container on Windows
5# Server 2016 or Windows 10.
6#
7# Maintainer: @jhowardmsft
8# -----------------------------------------------------------------------------------------
9
10
11# Prerequisites:
12# --------------
13#
14# 1. Windows Server 2016 or Windows 10 with all Windows updates applied. The major
15#    build number must be at least 14393. This can be confirmed, for example, by
16#    running the following from an elevated PowerShell prompt - this sample output
17#    is from a fully up to date machine as at mid-November 2016:
18#
19#    >> PS C:\> $(gin).WindowsBuildLabEx
20#    >> 14393.447.amd64fre.rs1_release_inmarket.161102-0100
21#
22# 2. Git for Windows (or another git client) must be installed. https://git-scm.com/download/win.
23#
24# 3. The machine must be configured to run containers. For example, by following
25#    the quick start guidance at https://msdn.microsoft.com/en-us/virtualization/windowscontainers/quick_start/quick_start or
26#    https://github.com/docker/labs/blob/master/windows/windows-containers/Setup.md
27#
28# 4. If building in a Hyper-V VM: For Windows Server 2016 using Windows Server
29#    containers as the default option, it is recommended you have at least 1GB
30#    of memory assigned; For Windows 10 where Hyper-V Containers are employed, you
31#    should have at least 4GB of memory assigned. Note also, to run Hyper-V
32#    containers in a VM, it is necessary to configure the VM for nested virtualization.
33
34# -----------------------------------------------------------------------------------------
35
36
37# Usage:
38# -----
39#
40#  The following steps should be run from an (elevated*) Windows PowerShell prompt.
41#
42#  (*In a default installation of containers on Windows following the quick-start guidance at
43#    https://msdn.microsoft.com/en-us/virtualization/windowscontainers/quick_start/quick_start,
44#    the docker.exe client must run elevated to be able to connect to the daemon).
45#
46# 1. Clone the sources from github.com:
47#
48#    >>   git clone https://github.com/docker/docker.git C:\go\src\github.com\docker\docker
49#    >>   Cloning into 'C:\go\src\github.com\docker\docker'...
50#    >>   remote: Counting objects: 186216, done.
51#    >>   remote: Compressing objects: 100% (21/21), done.
52#    >>   remote: Total 186216 (delta 5), reused 0 (delta 0), pack-reused 186195
53#    >>   Receiving objects: 100% (186216/186216), 104.32 MiB | 8.18 MiB/s, done.
54#    >>   Resolving deltas: 100% (123139/123139), done.
55#    >>   Checking connectivity... done.
56#    >>   Checking out files: 100% (3912/3912), done.
57#    >>   PS C:\>
58#
59#
60# 2. Change directory to the cloned docker sources:
61#
62#    >>   cd C:\go\src\github.com\docker\docker
63#
64#
65# 3. Build a docker image with the components required to build the docker binaries from source
66#    by running one of the following:
67#
68#    >>   docker build -t nativebuildimage -f Dockerfile.windows .
69#    >>   docker build -t nativebuildimage -f Dockerfile.windows -m 2GB .    (if using Hyper-V containers)
70#
71#
72# 4. Build the docker executable binaries by running one of the following:
73#
74#    >>   $DOCKER_GITCOMMIT=(git rev-parse --short HEAD)
75#    >>   docker run --name binaries -e DOCKER_GITCOMMIT=$DOCKER_GITCOMMIT nativebuildimage hack\make.ps1 -Binary
76#    >>   docker run --name binaries -e DOCKER_GITCOMMIT=$DOCKER_GITCOMMIT -m 2GB nativebuildimage hack\make.ps1 -Binary    (if using Hyper-V containers)
77#
78#
79# 5. Copy the binaries out of the container, replacing HostPath with an appropriate destination
80#    folder on the host system where you want the binaries to be located.
81#
82#    >>   docker cp binaries:C:\go\src\github.com\docker\docker\bundles\docker.exe C:\HostPath\docker.exe
83#    >>   docker cp binaries:C:\go\src\github.com\docker\docker\bundles\dockerd.exe C:\HostPath\dockerd.exe
84#
85#
86# 6. (Optional) Remove the interim container holding the built executable binaries:
87#
88#    >>    docker rm binaries
89#
90#
91# 7. (Optional) Remove the image used for the container in which the executable
92#    binaries are build. Tip - it may be useful to keep this image around if you need to
93#    build multiple times. Then you can take advantage of the builder cache to have an
94#    image which has all the components required to build the binaries already installed.
95#
96#    >>    docker rmi nativebuildimage
97#
98
99# -----------------------------------------------------------------------------------------
100
101
102#  The validation tests can only run directly on the host. This is because they calculate
103#  information from the git repo, but the .git directory is not passed into the image as
104#  it is excluded via .dockerignore. Run the following from a Windows PowerShell prompt
105#  (elevation is not required): (Note Go must be installed to run these tests)
106#
107#    >>   hack\make.ps1 -DCO -PkgImports -GoFormat
108
109
110# -----------------------------------------------------------------------------------------
111
112
113#  To run unit tests, ensure you have created the nativebuildimage above. Then run one of
114#  the following from an (elevated) Windows PowerShell prompt:
115#
116#    >>   docker run --rm nativebuildimage hack\make.ps1 -TestUnit
117#    >>   docker run --rm -m 2GB nativebuildimage hack\make.ps1 -TestUnit    (if using Hyper-V containers)
118
119
120# -----------------------------------------------------------------------------------------
121
122
123#  To run unit tests and binary build, ensure you have created the nativebuildimage above. Then
124#  run one of the following from an (elevated) Windows PowerShell prompt:
125#
126#    >>   docker run nativebuildimage hack\make.ps1 -All
127#    >>   docker run -m 2GB nativebuildimage hack\make.ps1 -All    (if using Hyper-V containers)
128
129# -----------------------------------------------------------------------------------------
130
131
132# Important notes:
133# ---------------
134#
135# Don't attempt to use a bind mount to pass a local directory as the bundles target
136# directory. It does not work (golang attempts for follow a mapped folder incorrectly).
137# Instead, use docker cp as per the example.
138#
139# go.zip is not removed from the image as it is used by the Windows CI servers
140# to ensure the host and image are running consistent versions of go.
141#
142# Nanoserver support is a work in progress. Although the image will build if the
143# FROM statement is updated, it will not work when running autogen through hack\make.ps1.
144# It is suspected that the required GCC utilities (eg gcc, windres, windmc) silently
145# quit due to the use of console hooks which are not available.
146#
147# The docker integration tests do not currently run in a container on Windows, predominantly
148# due to Windows not supporting privileged mode, so anything using a volume would fail.
149# They (along with the rest of the docker CI suite) can be run using
150# https://github.com/jhowardmsft/docker-w2wCIScripts/blob/master/runCI/Invoke-DockerCI.ps1.
151#
152# -----------------------------------------------------------------------------------------
153
154
155# The number of build steps below are explicitly minimised to improve performance.
156FROM microsoft/windowsservercore
157
158# Use PowerShell as the default shell
159SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
160
161# Environment variable notes:
162#  - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
163#  - FROM_DOCKERFILE is used for detection of building within a container.
164ENV GO_VERSION=1.10.3 `
165    GIT_VERSION=2.11.1 `
166    GOPATH=C:\go `
167    FROM_DOCKERFILE=1
168
169RUN `
170  Function Test-Nano() { `
171    $EditionId = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'EditionID').EditionId; `
172    return (($EditionId -eq 'ServerStandardNano') -or ($EditionId -eq 'ServerDataCenterNano') -or ($EditionId -eq 'NanoServer')); `
173  }`
174  `
175  Function Download-File([string] $source, [string] $target) { `
176    if (Test-Nano) { `
177      $handler = New-Object System.Net.Http.HttpClientHandler; `
178      $client = New-Object System.Net.Http.HttpClient($handler); `
179      $client.Timeout = New-Object System.TimeSpan(0, 30, 0); `
180      $cancelTokenSource = [System.Threading.CancellationTokenSource]::new(); `
181      $responseMsg = $client.GetAsync([System.Uri]::new($source), $cancelTokenSource.Token); `
182      $responseMsg.Wait(); `
183      if (!$responseMsg.IsCanceled) { `
184        $response = $responseMsg.Result; `
185        if ($response.IsSuccessStatusCode) { `
186          $downloadedFileStream = [System.IO.FileStream]::new($target, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write); `
187          $copyStreamOp = $response.Content.CopyToAsync($downloadedFileStream); `
188          $copyStreamOp.Wait(); `
189          $downloadedFileStream.Close(); `
190          if ($copyStreamOp.Exception -ne $null) { throw $copyStreamOp.Exception } `
191        } `
192      } else { `
193      Throw ("Failed to download " + $source) `
194      }`
195    } else { `
196      $webClient = New-Object System.Net.WebClient; `
197      $webClient.DownloadFile($source, $target); `
198    } `
199  } `
200  `
201  setx /M PATH $('C:\git\cmd;C:\git\usr\bin;'+$Env:PATH+';C:\gcc\bin;C:\go\bin'); `
202  `
203  Write-Host INFO: Downloading git...; `
204  $location='https://www.nuget.org/api/v2/package/GitForWindows/'+$Env:GIT_VERSION; `
205  Download-File $location C:\gitsetup.zip; `
206  `
207  Write-Host INFO: Downloading go...; `
208  Download-File $('https://golang.org/dl/go'+$Env:GO_VERSION+'.windows-amd64.zip') C:\go.zip; `
209  `
210  Write-Host INFO: Downloading compiler 1 of 3...; `
211  Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/gcc.zip C:\gcc.zip; `
212  `
213  Write-Host INFO: Downloading compiler 2 of 3...; `
214  Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/runtime.zip C:\runtime.zip; `
215  `
216  Write-Host INFO: Downloading compiler 3 of 3...; `
217  Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/binutils.zip C:\binutils.zip; `
218  `
219  Write-Host INFO: Extracting git...; `
220  Expand-Archive C:\gitsetup.zip C:\git-tmp; `
221  New-Item -Type Directory C:\git | Out-Null; `
222  Move-Item C:\git-tmp\tools\* C:\git\.; `
223  Remove-Item -Recurse -Force C:\git-tmp; `
224  `
225  Write-Host INFO: Expanding go...; `
226  Expand-Archive C:\go.zip -DestinationPath C:\; `
227  `
228  Write-Host INFO: Expanding compiler 1 of 3...; `
229  Expand-Archive C:\gcc.zip -DestinationPath C:\gcc -Force; `
230  Write-Host INFO: Expanding compiler 2 of 3...; `
231  Expand-Archive C:\runtime.zip -DestinationPath C:\gcc -Force; `
232  Write-Host INFO: Expanding compiler 3 of 3...; `
233  Expand-Archive C:\binutils.zip -DestinationPath C:\gcc -Force; `
234  `
235  Write-Host INFO: Removing downloaded files...; `
236  Remove-Item C:\gcc.zip; `
237  Remove-Item C:\runtime.zip; `
238  Remove-Item C:\binutils.zip; `
239  Remove-Item C:\gitsetup.zip; `
240  `
241  Write-Host INFO: Creating source directory...; `
242  New-Item -ItemType Directory -Path C:\go\src\github.com\docker\docker | Out-Null; `
243  `
244  Write-Host INFO: Configuring git core.autocrlf...; `
245  C:\git\cmd\git config --global core.autocrlf true; `
246  `
247  Write-Host INFO: Completed
248
249# Make PowerShell the default entrypoint
250ENTRYPOINT ["powershell.exe"]
251
252# Set the working directory to the location of the sources
253WORKDIR C:\go\src\github.com\docker\docker
254
255# Copy the sources into the container
256COPY . .
257