Skip to content

Commit d770b8b

Browse files
authored
Dockerfiles for .NET Core builds (dotnet#1)
* Dockerfile for .NET Core builds * Fix manifest.json path * Move build.ps1 and manifest to root
1 parent ea8654c commit d770b8b

File tree

35 files changed

+1427
-2
lines changed

35 files changed

+1427
-2
lines changed

README.md

+112-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,112 @@
1-
# dotnet-buildtools-prereqs-docker
2-
Used to maintain the docker images hosted at https://hub.docker.com/r/microsoft/dotnet-buildtools-prereqs/
1+
# Dockerfiles for .NET Core Builds
2+
3+
The Dockerfiles in this repository are used for building the .NET Core product. As such there are Dockerfiles for the various supported Linux distributions which setup the necessary prerequisites to build the .NET Core product.
4+
5+
## Where are the published images
6+
7+
The images produced from the Dockerfiles are published to the [microsoft/dotnet-buildtools-prereqs](https://hub.docker.com/r/microsoft/dotnet-buildtools-prereqs/) Docker Hub repository.
8+
9+
- [Most recent tags](https://hub.docker.com/r/microsoft/dotnet-buildtools-prereqs/tags/)
10+
- [Full list of tags](https://registry.hub.docker.com/v1/repositories/microsoft/dotnet-buildtools-prereqs/tags)
11+
12+
## How to identify an image
13+
14+
The tag format used by an image is `microsoft/dotnet-buildtools-prereqs:<linux-distribution-name>-<version>-<variant>-<dockerfile-commit-sha>-<date-time>`
15+
16+
- `<linux-distribution-name>` - name of the Linux distribution the image is based on
17+
- `<version>` - version of the Linux distribution
18+
- `<variant>` - name describing the specialization purpose of the image. Often special dependencies are needed for certain parts of the product. It can be beneficial to separate these dependencies into a separate Dockerfile/image.
19+
- `<dockerfile-commit-sha>` - Git commit SHA of the folder containing the Dockerfile the image was produced from
20+
- `<date-time>` - UTC timestamp (`yyyyMMddhhmmss`) of when the image was built
21+
22+
## How to modify or create a new image
23+
24+
There will be a need for modifying existing Dockerfiles or creating new ones. For example, when a new Linux distribution/version needs to be supported, a corresponding Dockerfile will need to be created. The following steps are a guideline for modifying/creating Dockerfiles.
25+
26+
1. Edit Dockerfiles
27+
- Add/Update the Dockerfile(s)
28+
- If new Dockerfile(s) were added, then update the [manifest](#manifest)
29+
30+
2. Validate the changes locally by running [build.ps1](./build.ps1). It is strongly suggested to specify the `-DockerfilePath` option to avoid the overhead of building all the images.
31+
32+
For example, if editing the [Fedora 24 Dockerfile](./src/fedora/24/Dockerfile), then run the following command to build just that Dockerfile.
33+
34+
```powershell
35+
.\build.ps1 -DockerfilePath "fedora/24"
36+
```
37+
38+
It is a good practice to use `--dry-run` option on the first attempt to verify what commands will get run.
39+
40+
```powershell
41+
.\build.ps1 -DockerfilePath "fedora/24" -ImageBuilderCustomArgs "--dry-run"
42+
```
43+
44+
Partial paths and wildcards in the `-DockerfilePath` option are also supported. The following example will build all the Fedora Dockerfiles.
45+
46+
```powershell
47+
.\build.ps1 -DockerfilePath "fedora/*"
48+
```
49+
50+
3. Prepare a PR
51+
52+
## Additional Info
53+
54+
### Source Folder Structure
55+
56+
The folder structure used in [src](./src) aligns with the tagging convention - `<linux-distribution-name>-<version>-<variant>`. For example, the Dockerfile used to produce the `microsoft/dotnet-buildtools-prereqs:ubuntu-17.04-debpkg-c4fd48a-20171610061631` image is stored in the [src/ubuntu/17.04/debpkg](./src/ubuntu/17.04/debpkg) folder.
57+
58+
### Manifest
59+
60+
The [manifest.json](./manifest.json) contains metadata used by the build infrastructure to produce the Docker images. The metadata describes which Dockerfiles to build, what tags to produce, and where to publish the images. It is critical that the manifest gets updated appropriately when Dockerfiles are added/removed. Each Dockerfile will have an entry that looks like the following.
61+
62+
```json
63+
"platforms": [
64+
{
65+
"dockerfile": "alpine/3.6",
66+
"os": "linux",
67+
"tags": {
68+
"alpine-3.6-$(System:DockerfileGitCommitSha)-$(System:TimeStamp)": {}
69+
}
70+
}
71+
]
72+
```
73+
74+
- `dockerfile` - relative path to the Dockerfile to build
75+
- `os` - (linux/windows) the OS type the Docker image is based on
76+
- `tags` - the collection of tags to create for the image
77+
- `$(System:DockerfileGitCommitSha)` and `$(System:TimeStamp)` - built in variable references that are evaluated at build time and substituted
78+
79+
**Note:** The position in manifest determines the sequence in which the image will be built.
80+
81+
### Image Dependency
82+
83+
A precondition for building an image is to ensure that the base image specified in the [FROM]((https://docs.docker.com/engine/reference/builder/#from)) statement of the Dockerfile is available either locally or can be pulled from a Docker registry. Some of the microsoft/dotnet-buildtools-prereqs Dockerfiles depend on other microsoft/dotnet-buildtools-prereqs Dockerfiles (e.g. [src/ubuntu/16.04/debpkg](./src/ubuntu/16.04/debpkg)). In these cases, the `FROM` reference should not include the `<dockerfile-commit-sha>-<date-time>` portion of the tags. This is referred to as a stable tag as it does not change from build to build. This pattern is used so that the Dockerfiles do not need constant updating as new versions of the base images are built. To support this scenario, the manifest entry for the base image must be defined to produce the stable tag.
84+
85+
```json
86+
"platforms": [
87+
{
88+
"dockerfile": "ubuntu/16.04",
89+
"os": "linux",
90+
"tags": {
91+
"ubuntu-16.04-$(System:DockerfileGitCommitSha)-$(System:TimeStamp)": {},
92+
"ubuntu-16.04": {
93+
"isLocal": true
94+
}
95+
}
96+
}
97+
]
98+
```
99+
100+
### Hooks
101+
102+
In certain cases, it is necessary to run custom logic before and after the Dockerfiles are built. For example, to build the Dockerfiles that are used for cross-gen builds, the rootfs that gets copied into the Docker image needs to be built on the host OS. To support these scenarios a `pre-build` or `post-build` bash or PowerShell script can be placed in a `hooks` folder next to the Dockerfile. The scripts will get invoked by the build process.
103+
104+
**Warning:** It is generally recommended to avoid the need to use hooks whenever possible.
105+
106+
### Image-Builder
107+
108+
The underlying tool used to build the Dockerfiles is called Image-Builder. Its source is located at [dotnet/docker-tools](https://github.com/dotnet/docker-tools)
109+
110+
----------
111+
112+
For any questions, please contact [email protected]

build.ps1

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[cmdletbinding()]
2+
param(
3+
[string]$DockerfilePath = "*",
4+
[string]$ImageBuilderCustomArgs,
5+
[string]$ImageBuilderImageName = 'microsoft/dotnet-buildtools-prereqs:image-builder-jessie-20180117125404'
6+
)
7+
8+
Set-StrictMode -Version Latest
9+
$ErrorActionPreference = 'Stop'
10+
11+
function ExecuteWithRetry($Command) {
12+
13+
$attempt = 0
14+
$maxRetries = 5
15+
$waitFactor = 6
16+
while ($attempt -lt $maxRetries) {
17+
try {
18+
& $Command @args
19+
break
20+
}
21+
catch {
22+
Write-Warning "$_"
23+
}
24+
25+
$attempt++
26+
if ($attempt -ne $maxRetries) {
27+
$waitTime = $attempt * $waitFactor
28+
Write-Host "Retry ${attempt}/${maxRetries} failed, retrying in $waitTime seconds..."
29+
Start-Sleep -Seconds ($waitTime)
30+
}
31+
else {
32+
throw "Retry ${attempt}/${maxRetries} failed, no more retries left."
33+
}
34+
}
35+
}
36+
37+
ExecuteWithRetry docker pull $ImageBuilderImageName
38+
39+
& docker run --rm `
40+
-v /var/run/docker.sock:/var/run/docker.sock `
41+
-v "${PSScriptRoot}:/repo" `
42+
-w /repo `
43+
$ImageBuilderImageName `
44+
build --manifest "manifest.json" --path "$DockerfilePath" "$ImageBuilderCustomArgs"
45+
46+
if ($LastExitCode -ne 0) {
47+
throw "Failed executing ImageBuilder."
48+
}

0 commit comments

Comments
 (0)