mirror of
https://github.com/moby/moby.git
synced 2026-01-14 12:08:07 +00:00
Compare commits
216 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7573ab867 | ||
|
|
9df87eaa9c | ||
|
|
de3f216113 | ||
|
|
20203f0c92 | ||
|
|
610250f06e | ||
|
|
63a0f1fe09 | ||
|
|
699e853be3 | ||
|
|
b7e0725e98 | ||
|
|
96746238b2 | ||
|
|
df2fe70049 | ||
|
|
8b83e09b9c | ||
|
|
26e9face5a | ||
|
|
9f62b37a62 | ||
|
|
3f87416881 | ||
|
|
6641852d51 | ||
|
|
8fc49af4ab | ||
|
|
b968cb92e6 | ||
|
|
62c7b25605 | ||
|
|
30134ab177 | ||
|
|
3da45c0fe7 | ||
|
|
941a07b339 | ||
|
|
cd5e05ee14 | ||
|
|
f825537119 | ||
|
|
a21381a55a | ||
|
|
2616ebc5ac | ||
|
|
cd0d7c49a6 | ||
|
|
7a5f3f8053 | ||
|
|
7cfd4b3471 | ||
|
|
1090c5fd4c | ||
|
|
c93e1e9e66 | ||
|
|
031fb72313 | ||
|
|
a96a97bf47 | ||
|
|
9b383dbd51 | ||
|
|
bed115e664 | ||
|
|
9ea2300535 | ||
|
|
5ae2d06a1f | ||
|
|
9fd854976f | ||
|
|
64cbbaa883 | ||
|
|
4100226e27 | ||
|
|
72f5fabd97 | ||
|
|
dadeec4205 | ||
|
|
f328486cb3 | ||
|
|
8e83d28f31 | ||
|
|
06eb6ab794 | ||
|
|
31cf0bf181 | ||
|
|
4df8f779b5 | ||
|
|
52df0048f6 | ||
|
|
110a9eaac1 | ||
|
|
d2998a4659 | ||
|
|
0e4548bbe1 | ||
|
|
8c12a6648b | ||
|
|
10c4ada049 | ||
|
|
10b536dd0f | ||
|
|
322149038a | ||
|
|
a8926de2a1 | ||
|
|
524de97334 | ||
|
|
0b2eecdc8a | ||
|
|
abff66b283 | ||
|
|
d9bdb61992 | ||
|
|
c627132dc8 | ||
|
|
13a31b67de | ||
|
|
ebedb1c496 | ||
|
|
bd5d9f3190 | ||
|
|
7e4f58d894 | ||
|
|
c8262e912f | ||
|
|
225551ddef | ||
|
|
fb75789691 | ||
|
|
12e3398f64 | ||
|
|
076d57104a | ||
|
|
8ce4ae1345 | ||
|
|
f0fe353ca6 | ||
|
|
04371160f8 | ||
|
|
e753cce70f | ||
|
|
9fd3a437a6 | ||
|
|
fc690c56b5 | ||
|
|
aefb643d79 | ||
|
|
d29ab757fb | ||
|
|
583018846c | ||
|
|
4d7792417e | ||
|
|
5802ca9e08 | ||
|
|
33572e98c1 | ||
|
|
52c7a5d96b | ||
|
|
101bd10d0e | ||
|
|
def679d0e0 | ||
|
|
cf8c728f3c | ||
|
|
e40c2410ca | ||
|
|
51a65e01ac | ||
|
|
0cf2b14994 | ||
|
|
21e6c282e6 | ||
|
|
42e7a15a63 | ||
|
|
01883e1177 | ||
|
|
25939ee45e | ||
|
|
8f5bbc24ef | ||
|
|
f6093fab79 | ||
|
|
f3761a5f38 | ||
|
|
691b44b4c3 | ||
|
|
5aa0c2cae2 | ||
|
|
0f2e972234 | ||
|
|
6acc1701ea | ||
|
|
6a9d742f12 | ||
|
|
8dfd907478 | ||
|
|
ba94fff321 | ||
|
|
7b692e1041 | ||
|
|
0d1aba547e | ||
|
|
4da19e2dca | ||
|
|
cb13848acd | ||
|
|
fe097e018c | ||
|
|
a166d959a0 | ||
|
|
0109eac486 | ||
|
|
d778bbab84 | ||
|
|
2dd577955c | ||
|
|
3ef71f9085 | ||
|
|
8fbfc2676f | ||
|
|
7e286efcd3 | ||
|
|
f29fe2daec | ||
|
|
3b90bb6ad3 | ||
|
|
171471b613 | ||
|
|
7d8c689923 | ||
|
|
75596bee28 | ||
|
|
29758a067f | ||
|
|
5d4ddce5ed | ||
|
|
a85bdbe1ca | ||
|
|
63e861c87e | ||
|
|
6a0a2c4f79 | ||
|
|
91f2d963c6 | ||
|
|
2bf66f725c | ||
|
|
1b27ab4c73 | ||
|
|
316231cced | ||
|
|
7bf0572f64 | ||
|
|
770ace39d8 | ||
|
|
5e4464798f | ||
|
|
2b5ec481e7 | ||
|
|
045de829e8 | ||
|
|
8cb02d8c58 | ||
|
|
515219b716 | ||
|
|
0393897695 | ||
|
|
7199300239 | ||
|
|
4ddde6dde5 | ||
|
|
e9075f70c7 | ||
|
|
cba986b340 | ||
|
|
b2d2f012b4 | ||
|
|
478f023783 | ||
|
|
52c35488a0 | ||
|
|
9980e64341 | ||
|
|
5ebd78d5f8 | ||
|
|
4b78386a3a | ||
|
|
21c1faed45 | ||
|
|
f6c2f20cee | ||
|
|
3d6908c79b | ||
|
|
1dc34e889c | ||
|
|
effd7661df | ||
|
|
f3e3266373 | ||
|
|
fd6316e631 | ||
|
|
fbe4db5be0 | ||
|
|
f9a356c7e9 | ||
|
|
6e7cc3b7e3 | ||
|
|
582b29f587 | ||
|
|
daa28fcf2d | ||
|
|
4cab584a9c | ||
|
|
1cc21c1b81 | ||
|
|
0b12468116 | ||
|
|
6570b654f4 | ||
|
|
d8d11bca37 | ||
|
|
0593c0600a | ||
|
|
a72fb70eb0 | ||
|
|
1bb2792c76 | ||
|
|
ce27df7b3c | ||
|
|
98cad005ca | ||
|
|
dca58c654a | ||
|
|
6149c333ff | ||
|
|
42bffae5ff | ||
|
|
a6818fd4cb | ||
|
|
45fe08c93c | ||
|
|
c508d13372 | ||
|
|
036398f512 | ||
|
|
a4957d2585 | ||
|
|
394eaa8495 | ||
|
|
d80f235c47 | ||
|
|
5ca9231b44 | ||
|
|
abcb4c556c | ||
|
|
47069ae18c | ||
|
|
ffa2c0b517 | ||
|
|
c0c146fc82 | ||
|
|
6295320d91 | ||
|
|
1cc1395fae | ||
|
|
0163808dbe | ||
|
|
9b62b83429 | ||
|
|
d5ffdeb76c | ||
|
|
4da8dedaab | ||
|
|
b14ffffffd | ||
|
|
173df30ac5 | ||
|
|
fe62290eed | ||
|
|
3083236871 | ||
|
|
2abf4d763b | ||
|
|
3fd34324a8 | ||
|
|
4ee3cc2531 | ||
|
|
48a0d8a8d1 | ||
|
|
a122104327 | ||
|
|
a74f0c2483 | ||
|
|
4f6786d861 | ||
|
|
3d902fe719 | ||
|
|
0da8917add | ||
|
|
623f6f7702 | ||
|
|
e57c432eff | ||
|
|
4952dc2844 | ||
|
|
e7b26fa1b1 | ||
|
|
f2463e1e86 | ||
|
|
139080d093 | ||
|
|
46e0317bc1 | ||
|
|
1da1a3ea87 | ||
|
|
bdf9baa207 | ||
|
|
99d5b53b99 | ||
|
|
7620f72fb8 | ||
|
|
304c56f7f5 | ||
|
|
b21e8f72f2 | ||
|
|
6875e7f1be |
2
.github/workflows/.windows.yml
vendored
2
.github/workflows/.windows.yml
vendored
@@ -15,7 +15,7 @@ on:
|
||||
default: false
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.19.3
|
||||
GO_VERSION: 1.19.5
|
||||
GOTESTLIST_VERSION: v0.2.0
|
||||
TESTSTAT_VERSION: v0.1.3
|
||||
WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore
|
||||
|
||||
9
.github/workflows/buildkit.yml
vendored
9
.github/workflows/buildkit.yml
vendored
@@ -13,7 +13,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
BUNDLES_OUTPUT: ./bundles
|
||||
DESTDIR: ./build
|
||||
|
||||
jobs:
|
||||
validate-dco:
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: binary
|
||||
path: ${{ env.BUNDLES_OUTPUT }}
|
||||
path: ${{ env.DESTDIR }}
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
@@ -69,10 +69,9 @@ jobs:
|
||||
-
|
||||
name: BuildKit ref
|
||||
run: |
|
||||
./hack/go-mod-prepare.sh
|
||||
# FIXME(thaJeztah) temporarily overriding version to use for tests; remove with the next release of buildkit
|
||||
# echo "BUILDKIT_REF=$(./hack/buildkit-ref)" >> $GITHUB_ENV
|
||||
echo "BUILDKIT_REF=4febae4f874bd8ef52dec30e988c8fe0bc96b3b9" >> $GITHUB_ENV
|
||||
echo "BUILDKIT_REF=3a391492c9d0b7428b6dcaa18c5aa3b5951fdacd" >> $GITHUB_ENV
|
||||
working-directory: moby
|
||||
-
|
||||
name: Checkout BuildKit ${{ env.BUILDKIT_REF }}
|
||||
@@ -107,7 +106,7 @@ jobs:
|
||||
env:
|
||||
CONTEXT: "."
|
||||
TEST_DOCKERD: "1"
|
||||
TEST_DOCKERD_BINARY: "./build/moby/binary-daemon/dockerd"
|
||||
TEST_DOCKERD_BINARY: "./build/moby/dockerd"
|
||||
TESTPKGS: "./${{ matrix.pkg }}"
|
||||
TESTFLAGS: "-v --parallel=1 --timeout=30m --run=//worker=dockerd$"
|
||||
working-directory: buildkit
|
||||
|
||||
61
.github/workflows/ci.yml
vendored
61
.github/workflows/ci.yml
vendored
@@ -15,7 +15,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
BUNDLES_OUTPUT: ./bundles
|
||||
DESTDIR: ./build
|
||||
|
||||
jobs:
|
||||
validate-dco:
|
||||
@@ -45,32 +45,53 @@ jobs:
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
-
|
||||
name: List artifacts
|
||||
run: |
|
||||
tree -nh ${{ env.DESTDIR }}
|
||||
-
|
||||
name: Check artifacts
|
||||
run: |
|
||||
find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} +
|
||||
-
|
||||
name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.target }}
|
||||
path: ${{ env.BUNDLES_OUTPUT }}
|
||||
path: ${{ env.DESTDIR }}
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
prepare-cross:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- validate-dco
|
||||
outputs:
|
||||
matrix: ${{ steps.platforms.outputs.matrix }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Create matrix
|
||||
id: platforms
|
||||
run: |
|
||||
matrix="$(docker buildx bake binary-cross --print | jq -cr '.target."binary-cross".platforms')"
|
||||
echo "matrix=$matrix" >> $GITHUB_OUTPUT
|
||||
-
|
||||
name: Show matrix
|
||||
run: |
|
||||
echo ${{ steps.platforms.outputs.matrix }}
|
||||
|
||||
cross:
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- validate-dco
|
||||
- prepare-cross
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform:
|
||||
- linux/amd64
|
||||
- linux/arm/v5
|
||||
- linux/arm/v6
|
||||
- linux/arm/v7
|
||||
- linux/arm64
|
||||
- linux/ppc64le
|
||||
- linux/s390x
|
||||
- windows/amd64
|
||||
- windows/arm64
|
||||
platform: ${{ fromJson(needs.prepare-cross.outputs.matrix) }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
@@ -89,14 +110,22 @@ jobs:
|
||||
name: Build
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: cross
|
||||
env:
|
||||
DOCKER_CROSSPLATFORMS: ${{ matrix.platform }}
|
||||
targets: all
|
||||
set: |
|
||||
*.platform=${{ matrix.platform }}
|
||||
-
|
||||
name: List artifacts
|
||||
run: |
|
||||
tree -nh ${{ env.DESTDIR }}
|
||||
-
|
||||
name: Check artifacts
|
||||
run: |
|
||||
find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} +
|
||||
-
|
||||
name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: cross-${{ env.PLATFORM_PAIR }}
|
||||
path: ${{ env.BUNDLES_OUTPUT }}
|
||||
path: ${{ env.DESTDIR }}
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
54
.github/workflows/test.yml
vendored
54
.github/workflows/test.yml
vendored
@@ -15,7 +15,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.19.3
|
||||
GO_VERSION: 1.19.5
|
||||
GOTESTLIST_VERSION: v0.2.0
|
||||
TESTSTAT_VERSION: v0.1.3
|
||||
ITG_CLI_MATRIX_SIZE: 6
|
||||
@@ -502,3 +502,55 @@ jobs:
|
||||
name: Create summary
|
||||
run: |
|
||||
teststat -markdown $(find /tmp/reports -type f -name '*.json' -print0 | xargs -0) >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
prepare-smoke:
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- validate-dco
|
||||
outputs:
|
||||
matrix: ${{ steps.platforms.outputs.matrix }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Create matrix
|
||||
id: platforms
|
||||
run: |
|
||||
matrix="$(docker buildx bake binary-smoketest --print | jq -cr '.target."binary-smoketest".platforms')"
|
||||
echo "matrix=$matrix" >> $GITHUB_OUTPUT
|
||||
-
|
||||
name: Show matrix
|
||||
run: |
|
||||
echo ${{ steps.platforms.outputs.matrix }}
|
||||
|
||||
smoke:
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- prepare-smoke
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: ${{ fromJson(needs.prepare-smoke.outputs.matrix) }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: binary-smoketest
|
||||
set: |
|
||||
*.platform=${{ matrix.platform }}
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -13,8 +13,6 @@ thumbs.db
|
||||
.bashrc
|
||||
.editorconfig
|
||||
|
||||
# top-level go.mod is not meant to be checked in
|
||||
/go.mod
|
||||
# build artifacts
|
||||
bundles/
|
||||
cli/winresources/*/*.syso
|
||||
|
||||
661
Dockerfile
661
Dockerfile
@@ -1,19 +1,36 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG CROSS="false"
|
||||
ARG SYSTEMD="false"
|
||||
ARG GO_VERSION=1.19.3
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG VPNKIT_VERSION=0.5.0
|
||||
|
||||
ARG GO_VERSION=1.19.5
|
||||
ARG BASE_DEBIAN_DISTRO="bullseye"
|
||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||
ARG XX_VERSION=1.1.2
|
||||
|
||||
FROM ${GOLANG_IMAGE} AS base
|
||||
ARG VPNKIT_VERSION=0.5.0
|
||||
ARG DOCKERCLI_VERSION=v17.06.2-ce
|
||||
|
||||
ARG SYSTEMD="false"
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG DOCKER_STATIC=1
|
||||
|
||||
# cross compilation helper
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
# dummy stage to make sure the image is built for deps that don't support some
|
||||
# architectures
|
||||
FROM --platform=$BUILDPLATFORM busybox AS build-dummy
|
||||
RUN mkdir -p /build
|
||||
FROM scratch AS binary-dummy
|
||||
COPY --from=build-dummy /build /build
|
||||
|
||||
# base
|
||||
FROM --platform=$BUILDPLATFORM ${GOLANG_IMAGE} AS base
|
||||
COPY --from=xx / /
|
||||
RUN echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
|
||||
ARG APT_MIRROR
|
||||
RUN sed -ri "s/(httpredir|deb).debian.org/${APT_MIRROR:-deb.debian.org}/g" /etc/apt/sources.list \
|
||||
&& sed -ri "s/(security).debian.org/${APT_MIRROR:-security.debian.org}/g" /etc/apt/sources.list
|
||||
ARG DEBIAN_FRONTEND
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y file
|
||||
ENV GO111MODULE=off
|
||||
|
||||
FROM base AS criu
|
||||
@@ -26,53 +43,67 @@ RUN --mount=type=cache,sharing=locked,id=moby-criu-aptlib,target=/var/lib/apt \
|
||||
&& apt-get install -y --no-install-recommends criu \
|
||||
&& install -D /usr/sbin/criu /build/criu
|
||||
|
||||
# registry
|
||||
FROM base AS registry-src
|
||||
WORKDIR /usr/src/registry
|
||||
RUN git init . && git remote add origin "https://github.com/distribution/distribution.git"
|
||||
|
||||
FROM base AS registry
|
||||
WORKDIR /go/src/github.com/docker/distribution
|
||||
|
||||
# REGISTRY_VERSION specifies the version of the registry to build and install
|
||||
# from the https://github.com/docker/distribution repository. This version of
|
||||
# the registry is used to test both schema 1 and schema 2 manifests. Generally,
|
||||
# the version specified here should match a current release.
|
||||
ARG REGISTRY_VERSION=v2.3.0
|
||||
|
||||
# REGISTRY_VERSION_SCHEMA1 specifies the version of the registry to build and
|
||||
# install from the https://github.com/docker/distribution repository. This is
|
||||
# an older (pre v2.3.0) version of the registry that only supports schema1
|
||||
# manifests. This version of the registry is not working on arm64, so installation
|
||||
# is skipped on that architecture.
|
||||
ARG REGISTRY_VERSION_SCHEMA1=v2.1.0
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=from=registry-src,src=/usr/src/registry,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=registry-build-$TARGETPLATFORM \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=tmpfs,target=/go/src/ \
|
||||
set -x \
|
||||
&& git clone https://github.com/docker/distribution.git . \
|
||||
&& git checkout -q "$REGISTRY_VERSION" \
|
||||
&& GOPATH="/go/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH" \
|
||||
go build -buildmode=pie -o /build/registry-v2 github.com/docker/distribution/cmd/registry \
|
||||
&& case $(dpkg --print-architecture) in \
|
||||
amd64|armhf|ppc64*|s390x) \
|
||||
git checkout -q "$REGISTRY_VERSION_SCHEMA1"; \
|
||||
GOPATH="/go/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH"; \
|
||||
go build -buildmode=pie -o /build/registry-v2-schema1 github.com/docker/distribution/cmd/registry; \
|
||||
;; \
|
||||
esac
|
||||
|
||||
FROM base AS swagger
|
||||
WORKDIR $GOPATH/src/github.com/go-swagger/go-swagger
|
||||
--mount=type=tmpfs,target=/go/src <<EOT
|
||||
set -ex
|
||||
git fetch -q --depth 1 origin "${REGISTRY_VERSION}" +refs/tags/*:refs/tags/*
|
||||
git checkout -q FETCH_HEAD
|
||||
export GOPATH="/go/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH"
|
||||
CGO_ENABLED=0 xx-go build -o /build/registry-v2 -v ./cmd/registry
|
||||
xx-verify /build/registry-v2
|
||||
case $TARGETPLATFORM in
|
||||
linux/amd64|linux/arm/v7|linux/ppc64le|linux/s390x)
|
||||
git fetch -q --depth 1 origin "${REGISTRY_VERSION_SCHEMA1}" +refs/tags/*:refs/tags/*
|
||||
git checkout -q FETCH_HEAD
|
||||
CGO_ENABLED=0 xx-go build -o /build/registry-v2-schema1 -v ./cmd/registry
|
||||
xx-verify /build/registry-v2-schema1
|
||||
;;
|
||||
esac
|
||||
EOT
|
||||
|
||||
# go-swagger
|
||||
FROM base AS swagger-src
|
||||
WORKDIR /usr/src/swagger
|
||||
# Currently uses a fork from https://github.com/kolyshkin/go-swagger/tree/golang-1.13-fix
|
||||
# TODO: move to under moby/ or fix upstream go-swagger to work for us.
|
||||
RUN git init . && git remote add origin "https://github.com/kolyshkin/go-swagger.git"
|
||||
# GO_SWAGGER_COMMIT specifies the version of the go-swagger binary to build and
|
||||
# install. Go-swagger is used in CI for validating swagger.yaml in hack/validate/swagger-gen
|
||||
#
|
||||
# Currently uses a fork from https://github.com/kolyshkin/go-swagger/tree/golang-1.13-fix,
|
||||
# TODO: move to under moby/ or fix upstream go-swagger to work for us.
|
||||
ENV GO_SWAGGER_COMMIT c56166c036004ba7a3a321e5951ba472b9ae298c
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
ARG GO_SWAGGER_COMMIT=c56166c036004ba7a3a321e5951ba472b9ae298c
|
||||
RUN git fetch -q --depth 1 origin "${GO_SWAGGER_COMMIT}" && git checkout -q FETCH_HEAD
|
||||
|
||||
FROM base AS swagger
|
||||
WORKDIR /go/src/github.com/go-swagger/go-swagger
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=from=swagger-src,src=/usr/src/swagger,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=swagger-build-$TARGETPLATFORM \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=tmpfs,target=/go/src/ \
|
||||
set -x \
|
||||
&& git clone https://github.com/kolyshkin/go-swagger.git . \
|
||||
&& git checkout -q "$GO_SWAGGER_COMMIT" \
|
||||
&& go build -o /build/swagger github.com/go-swagger/go-swagger/cmd/swagger
|
||||
--mount=type=tmpfs,target=/go/src/ <<EOT
|
||||
set -e
|
||||
xx-go build -o /build/swagger ./cmd/swagger
|
||||
xx-verify /build/swagger
|
||||
EOT
|
||||
|
||||
# frozen-images
|
||||
# See also frozenImages in "testutil/environment/protect.go" (which needs to
|
||||
@@ -96,80 +127,38 @@ RUN /download-frozen-image-v2.sh /build \
|
||||
hello-world:latest@sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9 \
|
||||
arm32v7/hello-world:latest@sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1
|
||||
|
||||
FROM base AS cross-false
|
||||
|
||||
FROM --platform=linux/amd64 base AS cross-true
|
||||
ARG DEBIAN_FRONTEND
|
||||
RUN dpkg --add-architecture arm64
|
||||
RUN dpkg --add-architecture armel
|
||||
RUN dpkg --add-architecture armhf
|
||||
RUN dpkg --add-architecture ppc64el
|
||||
RUN dpkg --add-architecture s390x
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-cross-true-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-cross-true-aptcache,target=/var/cache/apt \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
crossbuild-essential-arm64 \
|
||||
crossbuild-essential-armel \
|
||||
crossbuild-essential-armhf \
|
||||
crossbuild-essential-ppc64el \
|
||||
crossbuild-essential-s390x
|
||||
|
||||
FROM cross-${CROSS} AS dev-base
|
||||
|
||||
FROM dev-base AS runtime-dev-cross-false
|
||||
ARG DEBIAN_FRONTEND
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-cross-false-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-cross-false-aptcache,target=/var/cache/apt \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
binutils-mingw-w64 \
|
||||
g++-mingw-w64-x86-64 \
|
||||
libapparmor-dev \
|
||||
libbtrfs-dev \
|
||||
libdevmapper-dev \
|
||||
libseccomp-dev \
|
||||
libsystemd-dev \
|
||||
libudev-dev
|
||||
|
||||
FROM --platform=linux/amd64 runtime-dev-cross-false AS runtime-dev-cross-true
|
||||
ARG DEBIAN_FRONTEND
|
||||
# These crossbuild packages rely on gcc-<arch>, but this doesn't want to install
|
||||
# on non-amd64 systems, so other architectures cannot crossbuild amd64.
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-cross-true-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-cross-true-aptcache,target=/var/cache/apt \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
libapparmor-dev:arm64 \
|
||||
libapparmor-dev:armel \
|
||||
libapparmor-dev:armhf \
|
||||
libapparmor-dev:ppc64el \
|
||||
libapparmor-dev:s390x \
|
||||
libseccomp-dev:arm64 \
|
||||
libseccomp-dev:armel \
|
||||
libseccomp-dev:armhf \
|
||||
libseccomp-dev:ppc64el \
|
||||
libseccomp-dev:s390x
|
||||
|
||||
FROM runtime-dev-cross-${CROSS} AS runtime-dev
|
||||
|
||||
FROM base AS delve
|
||||
# delve
|
||||
FROM base AS delve-src
|
||||
WORKDIR /usr/src/delve
|
||||
RUN git init . && git remote add origin "https://github.com/go-delve/delve.git"
|
||||
# DELVE_VERSION specifies the version of the Delve debugger binary
|
||||
# from the https://github.com/go-delve/delve repository.
|
||||
# It can be used to run Docker with a possibility of
|
||||
# attaching debugger to it.
|
||||
#
|
||||
ARG DELVE_VERSION=v1.8.1
|
||||
# Delve on Linux is currently only supported on amd64 and arm64;
|
||||
ARG DELVE_VERSION=v1.9.1
|
||||
RUN git fetch -q --depth 1 origin "${DELVE_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||
|
||||
FROM base AS delve-build
|
||||
WORKDIR /usr/src/delve
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=from=delve-src,src=/usr/src/delve,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=delve-build-$TARGETPLATFORM \
|
||||
--mount=type=cache,target=/go/pkg/mod <<EOT
|
||||
set -e
|
||||
GO111MODULE=on xx-go build -o /build/dlv ./cmd/dlv
|
||||
xx-verify /build/dlv
|
||||
EOT
|
||||
|
||||
# delve is currently only supported on linux/amd64 and linux/arm64;
|
||||
# https://github.com/go-delve/delve/blob/v1.8.1/pkg/proc/native/support_sentinel.go#L1-L6
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
case $(dpkg --print-architecture) in \
|
||||
amd64|arm64) \
|
||||
GOBIN=/build/ GO111MODULE=on go install "github.com/go-delve/delve/cmd/dlv@${DELVE_VERSION}" \
|
||||
&& /build/dlv --help \
|
||||
;; \
|
||||
*) \
|
||||
mkdir -p /build/ \
|
||||
;; \
|
||||
esac
|
||||
FROM binary-dummy AS delve-windows
|
||||
FROM binary-dummy AS delve-linux-arm
|
||||
FROM binary-dummy AS delve-linux-ppc64le
|
||||
FROM binary-dummy AS delve-linux-s390x
|
||||
FROM delve-build AS delve-linux-amd64
|
||||
FROM delve-build AS delve-linux-arm64
|
||||
FROM delve-linux-${TARGETARCH} AS delve-linux
|
||||
FROM delve-${TARGETOS} AS delve
|
||||
|
||||
FROM base AS tomll
|
||||
# GOTOML_VERSION specifies the version of the tomll binary to build and install
|
||||
@@ -192,17 +181,46 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
GOBIN=/build/ GO111MODULE=on go install "github.com/tc-hib/go-winres@${GOWINRES_VERSION}" \
|
||||
&& /build/go-winres --help
|
||||
|
||||
FROM dev-base AS containerd
|
||||
# containerd
|
||||
FROM base AS containerd-src
|
||||
WORKDIR /usr/src/containerd
|
||||
RUN git init . && git remote add origin "https://github.com/containerd/containerd.git"
|
||||
# CONTAINERD_VERSION is used to build containerd binaries, and used for the
|
||||
# integration tests. The distributed docker .deb and .rpm packages depend on a
|
||||
# separate (containerd.io) package, which may be a different version as is
|
||||
# specified here. The containerd golang package is also pinned in vendor.mod.
|
||||
# When updating the binary version you may also need to update the vendor
|
||||
# version to pick up bug fixes or new APIs, however, usually the Go packages
|
||||
# are built from a commit from the master branch.
|
||||
ARG CONTAINERD_VERSION=v1.6.16
|
||||
RUN git fetch -q --depth 1 origin "${CONTAINERD_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||
|
||||
FROM base AS containerd-build
|
||||
WORKDIR /go/src/github.com/containerd/containerd
|
||||
ARG DEBIAN_FRONTEND
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-containerd-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-containerd-aptcache,target=/var/cache/apt \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
libbtrfs-dev
|
||||
ARG CONTAINERD_VERSION
|
||||
COPY /hack/dockerfile/install/install.sh /hack/dockerfile/install/containerd.installer /
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
PREFIX=/build /install.sh containerd
|
||||
apt-get update && xx-apt-get install -y --no-install-recommends \
|
||||
gcc libbtrfs-dev libsecret-1-dev
|
||||
ARG DOCKER_STATIC
|
||||
RUN --mount=from=containerd-src,src=/usr/src/containerd,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=containerd-build-$TARGETPLATFORM <<EOT
|
||||
set -e
|
||||
export CC=$(xx-info)-gcc
|
||||
export CGO_ENABLED=$([ "$DOCKER_STATIC" = "1" ] && echo "0" || echo "1")
|
||||
xx-go --wrap
|
||||
make $([ "$DOCKER_STATIC" = "1" ] && echo "STATIC=1") binaries
|
||||
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") bin/containerd
|
||||
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") bin/containerd-shim-runc-v2
|
||||
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") bin/ctr
|
||||
mkdir /build
|
||||
mv bin/containerd bin/containerd-shim-runc-v2 bin/ctr /build
|
||||
EOT
|
||||
|
||||
FROM containerd-build AS containerd-linux
|
||||
FROM binary-dummy AS containerd-windows
|
||||
FROM containerd-${TARGETOS} AS containerd
|
||||
|
||||
FROM base AS golangci_lint
|
||||
# FIXME: when updating golangci-lint, remove the temporary "nolint" in https://github.com/moby/moby/blob/7860686a8df15eea9def9e6189c6f9eca031bb6f/libnetwork/networkdb/cluster.go#L246
|
||||
@@ -226,46 +244,137 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
GOBIN=/build/ GO111MODULE=on go install "mvdan.cc/sh/v3/cmd/shfmt@${SHFMT_VERSION}" \
|
||||
&& /build/shfmt --version
|
||||
|
||||
FROM dev-base AS dockercli
|
||||
ARG DOCKERCLI_CHANNEL
|
||||
# dockercli
|
||||
FROM base AS dockercli-src
|
||||
WORKDIR /tmp/dockercli
|
||||
RUN git init . && git remote add origin "https://github.com/docker/cli.git"
|
||||
ARG DOCKERCLI_VERSION
|
||||
COPY /hack/dockerfile/install/install.sh /hack/dockerfile/install/dockercli.installer /
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
PREFIX=/build /install.sh dockercli
|
||||
RUN git fetch -q --depth 1 origin "${DOCKERCLI_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||
RUN [ -d ./components/cli ] && mv ./components/cli /usr/src/dockercli || mv /tmp/dockercli /usr/src/dockercli
|
||||
WORKDIR /usr/src/dockercli
|
||||
|
||||
FROM runtime-dev AS runc
|
||||
ARG RUNC_VERSION
|
||||
ARG RUNC_BUILDTAGS
|
||||
COPY /hack/dockerfile/install/install.sh /hack/dockerfile/install/runc.installer /
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
PREFIX=/build /install.sh runc
|
||||
FROM base AS dockercli
|
||||
WORKDIR /go/src/github.com/docker/cli
|
||||
ARG DOCKERCLI_VERSION
|
||||
ARG DOCKERCLI_CHANNEL=stable
|
||||
ARG TARGETPLATFORM
|
||||
RUN xx-apt-get install -y --no-install-recommends gcc libc6-dev
|
||||
RUN --mount=from=dockercli-src,src=/usr/src/dockercli,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=dockercli-build-$TARGETPLATFORM <<EOT
|
||||
set -e
|
||||
DOWNLOAD_URL="https://download.docker.com/linux/static/${DOCKERCLI_CHANNEL}/$(xx-info march)/docker-${DOCKERCLI_VERSION#v}.tgz"
|
||||
if curl --head --silent --fail "${DOWNLOAD_URL}" 1>/dev/null 2>&1; then
|
||||
mkdir /build
|
||||
curl -Ls "${DOWNLOAD_URL}" | tar -xz docker/docker
|
||||
mv docker/docker /build/docker
|
||||
else
|
||||
CGO_ENABLED=0 xx-go build -o /build/docker ./cmd/docker
|
||||
fi
|
||||
xx-verify /build/docker
|
||||
EOT
|
||||
|
||||
FROM dev-base AS tini
|
||||
# runc
|
||||
FROM base AS runc-src
|
||||
WORKDIR /usr/src/runc
|
||||
RUN git init . && git remote add origin "https://github.com/opencontainers/runc.git"
|
||||
# RUNC_VERSION should match the version that is used by the containerd version
|
||||
# that is used. If you need to update runc, open a pull request in the containerd
|
||||
# project first, and update both after that is merged. When updating RUNC_VERSION,
|
||||
# consider updating runc in vendor.mod accordingly.
|
||||
ARG RUNC_VERSION=v1.1.4
|
||||
RUN git fetch -q --depth 1 origin "${RUNC_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||
|
||||
FROM base AS runc-build
|
||||
WORKDIR /go/src/github.com/opencontainers/runc
|
||||
ARG DEBIAN_FRONTEND
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-runc-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-runc-aptcache,target=/var/cache/apt \
|
||||
apt-get update && xx-apt-get install -y --no-install-recommends \
|
||||
dpkg-dev gcc libc6-dev libseccomp-dev
|
||||
ARG DOCKER_STATIC
|
||||
RUN --mount=from=runc-src,src=/usr/src/runc,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=runc-build-$TARGETPLATFORM <<EOT
|
||||
set -e
|
||||
xx-go --wrap
|
||||
CGO_ENABLED=1 make "$([ "$DOCKER_STATIC" = "1" ] && echo "static" || echo "runc")"
|
||||
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") runc
|
||||
mkdir /build
|
||||
mv runc /build/
|
||||
EOT
|
||||
|
||||
FROM runc-build AS runc-linux
|
||||
FROM binary-dummy AS runc-windows
|
||||
FROM runc-${TARGETOS} AS runc
|
||||
|
||||
# tini
|
||||
FROM base AS tini-src
|
||||
WORKDIR /usr/src/tini
|
||||
RUN git init . && git remote add origin "https://github.com/krallin/tini.git"
|
||||
# TINI_VERSION specifies the version of tini (docker-init) to build. This
|
||||
# binary is used when starting containers with the `--init` option.
|
||||
ARG TINI_VERSION=v0.19.0
|
||||
RUN git fetch -q --depth 1 origin "${TINI_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||
|
||||
FROM base AS tini-build
|
||||
WORKDIR /go/src/github.com/krallin/tini
|
||||
ARG DEBIAN_FRONTEND
|
||||
ARG TINI_VERSION
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-tini-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-tini-aptcache,target=/var/cache/apt \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
cmake \
|
||||
vim-common
|
||||
COPY /hack/dockerfile/install/install.sh /hack/dockerfile/install/tini.installer /
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
PREFIX=/build /install.sh tini
|
||||
apt-get update && apt-get install -y --no-install-recommends cmake
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-tini-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-tini-aptcache,target=/var/cache/apt \
|
||||
xx-apt-get install -y --no-install-recommends \
|
||||
gcc libc6-dev
|
||||
RUN --mount=from=tini-src,src=/usr/src/tini,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=tini-build-$TARGETPLATFORM <<EOT
|
||||
set -e
|
||||
CC=$(xx-info)-gcc cmake .
|
||||
make tini-static
|
||||
xx-verify --static tini-static
|
||||
mkdir /build
|
||||
mv tini-static /build/docker-init
|
||||
EOT
|
||||
|
||||
FROM dev-base AS rootlesskit
|
||||
ARG ROOTLESSKIT_VERSION
|
||||
ARG PREFIX=/build
|
||||
COPY /hack/dockerfile/install/install.sh /hack/dockerfile/install/rootlesskit.installer /
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
FROM tini-build AS tini-linux
|
||||
FROM binary-dummy AS tini-windows
|
||||
FROM tini-${TARGETOS} AS tini
|
||||
|
||||
# rootlesskit
|
||||
FROM base AS rootlesskit-src
|
||||
WORKDIR /usr/src/rootlesskit
|
||||
RUN git init . && git remote add origin "https://github.com/rootless-containers/rootlesskit.git"
|
||||
# When updating, also update rootlesskit commit in vendor.mod accordingly.
|
||||
ARG ROOTLESSKIT_VERSION=v1.1.0
|
||||
RUN git fetch -q --depth 1 origin "${ROOTLESSKIT_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||
|
||||
FROM base AS rootlesskit-build
|
||||
WORKDIR /go/src/github.com/rootless-containers/rootlesskit
|
||||
ARG DEBIAN_FRONTEND
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-rootlesskit-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-rootlesskit-aptcache,target=/var/cache/apt \
|
||||
apt-get update && xx-apt-get install -y --no-install-recommends \
|
||||
gcc libc6-dev
|
||||
ENV GO111MODULE=on
|
||||
ARG DOCKER_STATIC
|
||||
RUN --mount=from=rootlesskit-src,src=/usr/src/rootlesskit,rw \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
/install.sh rootlesskit \
|
||||
&& "${PREFIX}"/rootlesskit --version \
|
||||
&& "${PREFIX}"/rootlesskit-docker-proxy --help
|
||||
COPY ./contrib/dockerd-rootless.sh /build
|
||||
COPY ./contrib/dockerd-rootless-setuptool.sh /build
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=rootlesskit-build-$TARGETPLATFORM <<EOT
|
||||
set -e
|
||||
export CGO_ENABLED=$([ "$DOCKER_STATIC" = "1" ] && echo "0" || echo "1")
|
||||
xx-go build -o /build/rootlesskit -ldflags="$([ "$DOCKER_STATIC" != "1" ] && echo "-linkmode=external")" ./cmd/rootlesskit
|
||||
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") /build/rootlesskit
|
||||
xx-go build -o /build/rootlesskit-docker-proxy -ldflags="$([ "$DOCKER_STATIC" != "1" ] && echo "-linkmode=external")" ./cmd/rootlesskit-docker-proxy
|
||||
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") /build/rootlesskit-docker-proxy
|
||||
EOT
|
||||
COPY ./contrib/dockerd-rootless.sh /build/
|
||||
COPY ./contrib/dockerd-rootless-setuptool.sh /build/
|
||||
|
||||
FROM rootlesskit-build AS rootlesskit-linux
|
||||
FROM binary-dummy AS rootlesskit-windows
|
||||
FROM rootlesskit-${TARGETOS} AS rootlesskit
|
||||
|
||||
FROM base AS crun
|
||||
ARG CRUN_VERSION=1.4.5
|
||||
@@ -305,8 +414,72 @@ FROM djs55/vpnkit:${VPNKIT_VERSION} AS vpnkit-linux-arm64
|
||||
FROM vpnkit-linux-${TARGETARCH} AS vpnkit-linux
|
||||
FROM vpnkit-${TARGETOS} AS vpnkit
|
||||
|
||||
# TODO: Some of this is only really needed for testing, it would be nice to split this up
|
||||
FROM runtime-dev AS dev-systemd-false
|
||||
# containerutility
|
||||
FROM base AS containerutil-src
|
||||
WORKDIR /usr/src/containerutil
|
||||
RUN git init . && git remote add origin "https://github.com/docker-archive/windows-container-utility.git"
|
||||
ARG CONTAINERUTILITY_VERSION=aa1ba87e99b68e0113bd27ec26c60b88f9d4ccd9
|
||||
RUN git fetch -q --depth 1 origin "${CONTAINERUTILITY_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||
|
||||
FROM base AS containerutil-build
|
||||
WORKDIR /usr/src/containerutil
|
||||
ARG TARGETPLATFORM
|
||||
RUN xx-apt-get install -y --no-install-recommends gcc g++ libc6-dev
|
||||
RUN --mount=from=containerutil-src,src=/usr/src/containerutil,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=containerutil-build-$TARGETPLATFORM <<EOT
|
||||
set -e
|
||||
CC="$(xx-info)-gcc" CXX="$(xx-info)-g++" make
|
||||
xx-verify --static containerutility.exe
|
||||
mkdir /build
|
||||
mv containerutility.exe /build/
|
||||
EOT
|
||||
|
||||
FROM binary-dummy AS containerutil-linux
|
||||
FROM containerutil-build AS containerutil-windows-amd64
|
||||
FROM containerutil-windows-${TARGETARCH} AS containerutil-windows
|
||||
FROM containerutil-${TARGETOS} AS containerutil
|
||||
|
||||
FROM base AS dev-systemd-false
|
||||
COPY --from=dockercli /build/ /usr/local/cli
|
||||
COPY --from=frozen-images /build/ /docker-frozen-images
|
||||
COPY --from=swagger /build/ /usr/local/bin/
|
||||
COPY --from=delve /build/ /usr/local/bin/
|
||||
COPY --from=tomll /build/ /usr/local/bin/
|
||||
COPY --from=gowinres /build/ /usr/local/bin/
|
||||
COPY --from=tini /build/ /usr/local/bin/
|
||||
COPY --from=registry /build/ /usr/local/bin/
|
||||
COPY --from=criu /build/ /usr/local/bin/
|
||||
COPY --from=gotestsum /build/ /usr/local/bin/
|
||||
COPY --from=golangci_lint /build/ /usr/local/bin/
|
||||
COPY --from=shfmt /build/ /usr/local/bin/
|
||||
COPY --from=runc /build/ /usr/local/bin/
|
||||
COPY --from=containerd /build/ /usr/local/bin/
|
||||
COPY --from=rootlesskit /build/ /usr/local/bin/
|
||||
COPY --from=vpnkit / /usr/local/bin/
|
||||
COPY --from=containerutil /build/ /usr/local/bin/
|
||||
COPY --from=crun /build/ /usr/local/bin/
|
||||
COPY hack/dockerfile/etc/docker/ /etc/docker/
|
||||
ENV PATH=/usr/local/cli:$PATH
|
||||
WORKDIR /go/src/github.com/docker/docker
|
||||
VOLUME /var/lib/docker
|
||||
VOLUME /home/unprivilegeduser/.local/share/docker
|
||||
# Wrap all commands in the "docker-in-docker" script to allow nested containers
|
||||
ENTRYPOINT ["hack/dind"]
|
||||
|
||||
FROM dev-systemd-false AS dev-systemd-true
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-dev-aptcache,target=/var/cache/apt \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
dbus \
|
||||
dbus-user-session \
|
||||
systemd \
|
||||
systemd-sysv
|
||||
RUN mkdir -p hack \
|
||||
&& curl -o hack/dind-systemd https://raw.githubusercontent.com/AkihiroSuda/containerized-systemd/b70bac0daeea120456764248164c21684ade7d0d/docker-entrypoint.sh \
|
||||
&& chmod +x hack/dind-systemd
|
||||
ENTRYPOINT ["hack/dind-systemd"]
|
||||
|
||||
FROM dev-systemd-${SYSTEMD} AS dev-base
|
||||
ARG DEBIAN_FRONTEND
|
||||
RUN groupadd -r docker
|
||||
RUN useradd --create-home --gid docker unprivilegeduser \
|
||||
@@ -350,116 +523,120 @@ RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
||||
xz-utils \
|
||||
zip \
|
||||
zstd
|
||||
|
||||
|
||||
# Switch to use iptables instead of nftables (to match the CI hosts)
|
||||
# TODO use some kind of runtime auto-detection instead if/when nftables is supported (https://github.com/moby/moby/issues/26824)
|
||||
RUN update-alternatives --set iptables /usr/sbin/iptables-legacy || true \
|
||||
&& update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy || true \
|
||||
&& update-alternatives --set arptables /usr/sbin/arptables-legacy || true
|
||||
|
||||
ARG YAMLLINT_VERSION=1.27.1
|
||||
RUN pip3 install yamllint==${YAMLLINT_VERSION}
|
||||
|
||||
COPY --from=dockercli /build/ /usr/local/cli
|
||||
COPY --from=frozen-images /build/ /docker-frozen-images
|
||||
COPY --from=swagger /build/ /usr/local/bin/
|
||||
COPY --from=delve /build/ /usr/local/bin/
|
||||
COPY --from=tomll /build/ /usr/local/bin/
|
||||
COPY --from=gowinres /build/ /usr/local/bin/
|
||||
COPY --from=tini /build/ /usr/local/bin/
|
||||
COPY --from=registry /build/ /usr/local/bin/
|
||||
COPY --from=criu /build/ /usr/local/bin/
|
||||
COPY --from=gotestsum /build/ /usr/local/bin/
|
||||
COPY --from=golangci_lint /build/ /usr/local/bin/
|
||||
COPY --from=shfmt /build/ /usr/local/bin/
|
||||
COPY --from=runc /build/ /usr/local/bin/
|
||||
COPY --from=containerd /build/ /usr/local/bin/
|
||||
COPY --from=rootlesskit /build/ /usr/local/bin/
|
||||
COPY --from=vpnkit / /usr/local/bin/
|
||||
COPY --from=crun /build/ /usr/local/bin/
|
||||
COPY hack/dockerfile/etc/docker/ /etc/docker/
|
||||
ENV PATH=/usr/local/cli:$PATH
|
||||
ARG DOCKER_BUILDTAGS
|
||||
ENV DOCKER_BUILDTAGS="${DOCKER_BUILDTAGS}"
|
||||
WORKDIR /go/src/github.com/docker/docker
|
||||
VOLUME /var/lib/docker
|
||||
VOLUME /home/unprivilegeduser/.local/share/docker
|
||||
# Wrap all commands in the "docker-in-docker" script to allow nested containers
|
||||
ENTRYPOINT ["hack/dind"]
|
||||
|
||||
FROM dev-systemd-false AS dev-systemd-true
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-dev-aptcache,target=/var/cache/apt \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
dbus \
|
||||
dbus-user-session \
|
||||
systemd \
|
||||
systemd-sysv
|
||||
RUN mkdir -p hack \
|
||||
&& curl -o hack/dind-systemd https://raw.githubusercontent.com/AkihiroSuda/containerized-systemd/b70bac0daeea120456764248164c21684ade7d0d/docker-entrypoint.sh \
|
||||
&& chmod +x hack/dind-systemd
|
||||
ENTRYPOINT ["hack/dind-systemd"]
|
||||
apt-get update && apt-get install --no-install-recommends -y \
|
||||
gcc \
|
||||
pkg-config \
|
||||
dpkg-dev \
|
||||
libapparmor-dev \
|
||||
libdevmapper-dev \
|
||||
libseccomp-dev \
|
||||
libsecret-1-dev \
|
||||
libsystemd-dev \
|
||||
libudev-dev
|
||||
|
||||
FROM dev-systemd-${SYSTEMD} AS dev
|
||||
|
||||
FROM runtime-dev AS binary-base
|
||||
ARG DOCKER_GITCOMMIT=HEAD
|
||||
ENV DOCKER_GITCOMMIT=${DOCKER_GITCOMMIT}
|
||||
ARG VERSION
|
||||
ENV VERSION=${VERSION}
|
||||
ARG PLATFORM
|
||||
ENV PLATFORM=${PLATFORM}
|
||||
ARG PRODUCT
|
||||
ENV PRODUCT=${PRODUCT}
|
||||
ARG DEFAULT_PRODUCT_LICENSE
|
||||
ENV DEFAULT_PRODUCT_LICENSE=${DEFAULT_PRODUCT_LICENSE}
|
||||
ARG PACKAGER_NAME
|
||||
ENV PACKAGER_NAME=${PACKAGER_NAME}
|
||||
ARG DOCKER_BUILDTAGS
|
||||
ENV DOCKER_BUILDTAGS="${DOCKER_BUILDTAGS}"
|
||||
ENV PREFIX=/build
|
||||
# TODO: This is here because hack/make.sh binary copies these extras binaries
|
||||
# from $PATH into the bundles dir.
|
||||
# It would be nice to handle this in a different way.
|
||||
COPY --from=tini /build/ /usr/local/bin/
|
||||
COPY --from=runc /build/ /usr/local/bin/
|
||||
COPY --from=containerd /build/ /usr/local/bin/
|
||||
COPY --from=rootlesskit /build/ /usr/local/bin/
|
||||
COPY --from=vpnkit / /usr/local/bin/
|
||||
COPY --from=gowinres /build/ /usr/local/bin/
|
||||
FROM base AS build
|
||||
COPY --from=gowinres /build/ /usr/local/bin/
|
||||
WORKDIR /go/src/github.com/docker/docker
|
||||
|
||||
FROM binary-base AS build-binary
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
--mount=type=bind,target=.,ro \
|
||||
ENV GO111MODULE=off
|
||||
ENV CGO_ENABLED=1
|
||||
ARG DEBIAN_FRONTEND
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-build-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-build-aptcache,target=/var/cache/apt \
|
||||
apt-get update && apt-get install --no-install-recommends -y \
|
||||
clang \
|
||||
lld \
|
||||
llvm
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=type=cache,sharing=locked,id=moby-build-aptlib,target=/var/lib/apt \
|
||||
--mount=type=cache,sharing=locked,id=moby-build-aptcache,target=/var/cache/apt \
|
||||
xx-apt-get install --no-install-recommends -y \
|
||||
dpkg-dev \
|
||||
gcc \
|
||||
libapparmor-dev \
|
||||
libc6-dev \
|
||||
libdevmapper-dev \
|
||||
libseccomp-dev \
|
||||
libsecret-1-dev \
|
||||
libsystemd-dev \
|
||||
libudev-dev
|
||||
ARG DOCKER_BUILDTAGS
|
||||
ARG DOCKER_DEBUG
|
||||
ARG DOCKER_GITCOMMIT=HEAD
|
||||
ARG DOCKER_LDFLAGS
|
||||
ARG DOCKER_STATIC
|
||||
ARG VERSION
|
||||
ARG PLATFORM
|
||||
ARG PRODUCT
|
||||
ARG DEFAULT_PRODUCT_LICENSE
|
||||
ARG PACKAGER_NAME
|
||||
# PREFIX overrides DEST dir in make.sh script otherwise it fails because of
|
||||
# read only mount in current work dir
|
||||
ENV PREFIX=/tmp
|
||||
RUN <<EOT
|
||||
# in bullseye arm64 target does not link with lld so configure it to use ld instead
|
||||
if [ "$(xx-info arch)" = "arm64" ]; then
|
||||
XX_CC_PREFER_LINKER=ld xx-clang --setup-target-triple
|
||||
fi
|
||||
EOT
|
||||
RUN --mount=type=bind,target=. \
|
||||
--mount=type=tmpfs,target=cli/winresources/dockerd \
|
||||
--mount=type=tmpfs,target=cli/winresources/docker-proxy \
|
||||
hack/make.sh binary
|
||||
|
||||
FROM binary-base AS build-dynbinary
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
--mount=type=bind,target=.,ro \
|
||||
--mount=type=tmpfs,target=cli/winresources/dockerd \
|
||||
--mount=type=tmpfs,target=cli/winresources/docker-proxy \
|
||||
hack/make.sh dynbinary
|
||||
|
||||
FROM binary-base AS build-cross
|
||||
ARG DOCKER_CROSSPLATFORMS
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
--mount=type=bind,target=.,ro \
|
||||
--mount=type=tmpfs,target=cli/winresources/dockerd \
|
||||
--mount=type=tmpfs,target=cli/winresources/docker-proxy \
|
||||
hack/make.sh cross
|
||||
--mount=type=cache,target=/root/.cache/go-build,id=moby-build-$TARGETPLATFORM <<EOT
|
||||
set -e
|
||||
target=$([ "$DOCKER_STATIC" = "1" ] && echo "binary" || echo "dynbinary")
|
||||
xx-go --wrap
|
||||
PKG_CONFIG=$(xx-go env PKG_CONFIG) ./hack/make.sh $target
|
||||
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") /tmp/bundles/${target}-daemon/dockerd$([ "$(xx-info os)" = "windows" ] && echo ".exe")
|
||||
xx-verify $([ "$DOCKER_STATIC" = "1" ] && echo "--static") /tmp/bundles/${target}-daemon/docker-proxy$([ "$(xx-info os)" = "windows" ] && echo ".exe")
|
||||
mkdir /build
|
||||
mv /tmp/bundles/${target}-daemon/* /build/
|
||||
EOT
|
||||
|
||||
# usage:
|
||||
# > docker buildx bake binary
|
||||
# > DOCKER_STATIC=0 docker buildx bake binary
|
||||
# or
|
||||
# > make binary
|
||||
# > make dynbinary
|
||||
FROM scratch AS binary
|
||||
COPY --from=build-binary /build/bundles/ /
|
||||
COPY --from=build /build/ /
|
||||
|
||||
FROM scratch AS dynbinary
|
||||
COPY --from=build-dynbinary /build/bundles/ /
|
||||
# usage:
|
||||
# > docker buildx bake all
|
||||
FROM scratch AS all
|
||||
COPY --from=tini /build/ /
|
||||
COPY --from=runc /build/ /
|
||||
COPY --from=containerd /build/ /
|
||||
COPY --from=rootlesskit /build/ /
|
||||
COPY --from=containerutil /build/ /
|
||||
COPY --from=vpnkit / /
|
||||
COPY --from=build /build /
|
||||
|
||||
FROM scratch AS cross
|
||||
COPY --from=build-cross /build/bundles/ /
|
||||
# smoke tests
|
||||
# usage:
|
||||
# > docker buildx bake binary-smoketest
|
||||
FROM --platform=$TARGETPLATFORM base AS smoketest
|
||||
WORKDIR /usr/local/bin
|
||||
COPY --from=build /build .
|
||||
RUN <<EOT
|
||||
set -ex
|
||||
file dockerd
|
||||
dockerd --version
|
||||
file docker-proxy
|
||||
docker-proxy --version
|
||||
EOT
|
||||
|
||||
FROM dev AS final
|
||||
COPY . /go/src/github.com/docker/docker
|
||||
# usage:
|
||||
# > make shell
|
||||
# > SYSTEMD=true make shell
|
||||
FROM dev-base AS dev
|
||||
COPY . .
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
ARG GO_VERSION=1.19.3
|
||||
ARG GO_VERSION=1.19.5
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine AS base
|
||||
ENV GO111MODULE=off
|
||||
RUN apk --no-cache add \
|
||||
bash \
|
||||
btrfs-progs-dev \
|
||||
build-base \
|
||||
curl \
|
||||
lvm2-dev \
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
# This represents the bare minimum required to build and test Docker.
|
||||
|
||||
ARG GO_VERSION=1.19.3
|
||||
ARG GO_VERSION=1.19.5
|
||||
|
||||
ARG BASE_DEBIAN_DISTRO="bullseye"
|
||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||
@@ -24,10 +24,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
curl \
|
||||
cmake \
|
||||
gcc \
|
||||
git \
|
||||
libapparmor-dev \
|
||||
libbtrfs-dev \
|
||||
libdevmapper-dev \
|
||||
libseccomp-dev \
|
||||
ca-certificates \
|
||||
|
||||
@@ -165,10 +165,10 @@ FROM microsoft/windowsservercore
|
||||
# Use PowerShell as the default shell
|
||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||
|
||||
ARG GO_VERSION=1.19.3
|
||||
ARG GO_VERSION=1.19.5
|
||||
ARG GOTESTSUM_VERSION=v1.8.2
|
||||
ARG GOWINRES_VERSION=v0.3.0
|
||||
ARG CONTAINERD_VERSION=v1.6.10
|
||||
ARG CONTAINERD_VERSION=v1.6.16
|
||||
|
||||
# Environment variable notes:
|
||||
# - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
|
||||
|
||||
34
Makefile
34
Makefile
@@ -31,7 +31,6 @@ export VALIDATE_ORIGIN_BRANCH
|
||||
# make DOCKER_LDFLAGS="-X github.com/docker/docker/daemon/graphdriver.priority=overlay2,devicemapper" dynbinary
|
||||
#
|
||||
DOCKER_ENVS := \
|
||||
-e DOCKER_CROSSPLATFORMS \
|
||||
-e BUILD_APT_MIRROR \
|
||||
-e BUILDFLAGS \
|
||||
-e KEEPBUNDLE \
|
||||
@@ -142,17 +141,7 @@ endif
|
||||
|
||||
BUILD_OPTS := ${BUILD_APT_MIRROR} ${DOCKER_BUILD_ARGS} ${DOCKER_BUILD_OPTS} -f "$(DOCKERFILE)"
|
||||
BUILD_CMD := $(BUILDX) build
|
||||
|
||||
# This is used for the legacy "build" target and anything still depending on it
|
||||
BUILD_CROSS =
|
||||
ifdef DOCKER_CROSS
|
||||
BUILD_CROSS = --build-arg CROSS=$(DOCKER_CROSS)
|
||||
endif
|
||||
ifdef DOCKER_CROSSPLATFORMS
|
||||
BUILD_CROSS = --build-arg CROSS=true
|
||||
endif
|
||||
|
||||
VERSION_AUTOGEN_ARGS = --build-arg VERSION --build-arg DOCKER_GITCOMMIT --build-arg PRODUCT --build-arg PLATFORM --build-arg DEFAULT_PRODUCT_LICENSE --build-arg PACKAGER_NAME
|
||||
BAKE_CMD := $(BUILDX) bake
|
||||
|
||||
default: binary
|
||||
|
||||
@@ -160,14 +149,13 @@ all: build ## validate all checks, build linux binaries, run all tests,\ncross b
|
||||
$(DOCKER_RUN_DOCKER) bash -c 'hack/validate/default && hack/make.sh'
|
||||
|
||||
binary: bundles ## build statically linked linux binaries
|
||||
$(BUILD_CMD) $(BUILD_OPTS) --output=bundles/ --target=$@ $(VERSION_AUTOGEN_ARGS) .
|
||||
$(BAKE_CMD) binary
|
||||
|
||||
dynbinary: bundles ## build dynamically linked linux binaries
|
||||
$(BUILD_CMD) $(BUILD_OPTS) --output=bundles/ --target=$@ $(VERSION_AUTOGEN_ARGS) .
|
||||
$(BAKE_CMD) dynbinary
|
||||
|
||||
cross: BUILD_OPTS += --build-arg CROSS=true --build-arg DOCKER_CROSSPLATFORMS
|
||||
cross: bundles ## cross build the binaries for darwin, freebsd and\nwindows
|
||||
$(BUILD_CMD) $(BUILD_OPTS) --output=bundles/ --target=$@ $(VERSION_AUTOGEN_ARGS) .
|
||||
cross: bundles ## cross build the binaries
|
||||
$(BAKE_CMD) binary-cross
|
||||
|
||||
bundles:
|
||||
mkdir bundles
|
||||
@@ -190,18 +178,18 @@ run: build ## run the docker daemon in a container
|
||||
|
||||
.PHONY: build
|
||||
ifeq ($(BIND_DIR), .)
|
||||
build: shell_target := --target=dev
|
||||
build: shell_target := --target=dev-base
|
||||
else
|
||||
build: shell_target := --target=final
|
||||
build: shell_target := --target=dev
|
||||
endif
|
||||
build: bundles
|
||||
$(BUILD_CMD) $(BUILD_OPTS) $(shell_target) --load $(BUILD_CROSS) -t "$(DOCKER_IMAGE)" .
|
||||
$(BUILD_CMD) $(BUILD_OPTS) $(shell_target) --load -t "$(DOCKER_IMAGE)" .
|
||||
|
||||
shell: build ## start a shell inside the build env
|
||||
$(DOCKER_RUN_DOCKER) bash
|
||||
|
||||
test: build test-unit ## run the unit, integration and docker-py tests
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary cross test-integration test-docker-py
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary test-integration test-docker-py
|
||||
|
||||
test-docker-py: build ## run the docker-py tests
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary test-docker-py
|
||||
@@ -228,8 +216,8 @@ validate: build ## validate DCO, Seccomp profile generation, gofmt,\n./pkg/ isol
|
||||
validate-%: build ## validate specific check
|
||||
$(DOCKER_RUN_DOCKER) hack/validate/$*
|
||||
|
||||
win: build ## cross build the binary for windows
|
||||
$(DOCKER_RUN_DOCKER) DOCKER_CROSSPLATFORMS=windows/amd64 hack/make.sh cross
|
||||
win: bundles ## cross build the binary for windows
|
||||
$(BAKE_CMD) --set *.platform=windows/amd64 binary
|
||||
|
||||
.PHONY: swagger-gen
|
||||
swagger-gen:
|
||||
|
||||
@@ -2343,6 +2343,8 @@ definitions:
|
||||
type: "string"
|
||||
error:
|
||||
type: "string"
|
||||
errorDetail:
|
||||
$ref: "#/definitions/ErrorDetail"
|
||||
status:
|
||||
type: "string"
|
||||
progress:
|
||||
@@ -8725,6 +8727,10 @@ paths:
|
||||
IdentityToken: "9cbaf023786cd7..."
|
||||
204:
|
||||
description: "No error"
|
||||
401:
|
||||
description: "Auth error"
|
||||
schema:
|
||||
$ref: "#/definitions/ErrorResponse"
|
||||
500:
|
||||
description: "Server error"
|
||||
schema:
|
||||
|
||||
@@ -50,7 +50,7 @@ func (args Args) Keys() []string {
|
||||
// MarshalJSON returns a JSON byte representation of the Args
|
||||
func (args Args) MarshalJSON() ([]byte, error) {
|
||||
if len(args.fields) == 0 {
|
||||
return []byte{}, nil
|
||||
return []byte("{}"), nil
|
||||
}
|
||||
return json.Marshal(args.fields)
|
||||
}
|
||||
@@ -108,9 +108,6 @@ func FromJSON(p string) (Args, error) {
|
||||
|
||||
// UnmarshalJSON populates the Args from JSON encode bytes
|
||||
func (args Args) UnmarshalJSON(raw []byte) error {
|
||||
if len(raw) == 0 {
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(raw, &args.fields)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package filters // import "github.com/docker/docker/api/types/filters"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
@@ -8,6 +9,26 @@ import (
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestMarshalJSON(t *testing.T) {
|
||||
fields := map[string]map[string]bool{
|
||||
"created": {"today": true},
|
||||
"image.name": {"ubuntu*": true, "*untu": true},
|
||||
}
|
||||
a := Args{fields: fields}
|
||||
|
||||
_, err := a.MarshalJSON()
|
||||
if err != nil {
|
||||
t.Errorf("failed to marshal the filters: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalJSONWithEmpty(t *testing.T) {
|
||||
_, err := json.Marshal(NewArgs())
|
||||
if err != nil {
|
||||
t.Errorf("failed to marshal the filters: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToJSON(t *testing.T) {
|
||||
fields := map[string]map[string]bool{
|
||||
"created": {"today": true},
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/daemon/images"
|
||||
"github.com/docker/docker/libnetwork"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/streamformatter"
|
||||
"github.com/docker/go-units"
|
||||
@@ -81,6 +82,7 @@ type Opt struct {
|
||||
// Builder can build using BuildKit backend
|
||||
type Builder struct {
|
||||
controller *control.Controller
|
||||
dnsconfig config.DNSConfig
|
||||
reqBodyHandler *reqBodyHandler
|
||||
|
||||
mu sync.Mutex
|
||||
@@ -97,6 +99,7 @@ func New(opt Opt) (*Builder, error) {
|
||||
}
|
||||
b := &Builder{
|
||||
controller: c,
|
||||
dnsconfig: opt.DNSConfig,
|
||||
reqBodyHandler: reqHandler,
|
||||
jobs: map[string]*buildJob{},
|
||||
}
|
||||
@@ -311,7 +314,7 @@ func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.
|
||||
return nil, errors.Errorf("network mode %q not supported by buildkit", opt.Options.NetworkMode)
|
||||
}
|
||||
|
||||
extraHosts, err := toBuildkitExtraHosts(opt.Options.ExtraHosts)
|
||||
extraHosts, err := toBuildkitExtraHosts(opt.Options.ExtraHosts, b.dnsconfig.HostGatewayIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -551,18 +554,28 @@ func (j *buildJob) SetUpload(ctx context.Context, rc io.ReadCloser) error {
|
||||
}
|
||||
|
||||
// toBuildkitExtraHosts converts hosts from docker key:value format to buildkit's csv format
|
||||
func toBuildkitExtraHosts(inp []string) (string, error) {
|
||||
func toBuildkitExtraHosts(inp []string, hostGatewayIP net.IP) (string, error) {
|
||||
if len(inp) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
hosts := make([]string, 0, len(inp))
|
||||
for _, h := range inp {
|
||||
parts := strings.Split(h, ":")
|
||||
|
||||
if len(parts) != 2 || parts[0] == "" || net.ParseIP(parts[1]) == nil {
|
||||
host, ip, ok := strings.Cut(h, ":")
|
||||
if !ok || host == "" || ip == "" {
|
||||
return "", errors.Errorf("invalid host %s", h)
|
||||
}
|
||||
hosts = append(hosts, parts[0]+"="+parts[1])
|
||||
// If the IP Address is a "host-gateway", replace this value with the
|
||||
// IP address stored in the daemon level HostGatewayIP config variable.
|
||||
if ip == opts.HostGatewayName {
|
||||
gateway := hostGatewayIP.String()
|
||||
if gateway == "" {
|
||||
return "", fmt.Errorf("unable to derive the IP value for host-gateway")
|
||||
}
|
||||
ip = gateway
|
||||
} else if net.ParseIP(ip) == nil {
|
||||
return "", fmt.Errorf("invalid host %s", h)
|
||||
}
|
||||
hosts = append(hosts, host+"="+ip)
|
||||
}
|
||||
return strings.Join(hosts, ","), nil
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ func (iface *lnInterface) Set(s *specs.Spec) error {
|
||||
s.Hooks = &specs.Hooks{
|
||||
Prestart: []specs.Hook{{
|
||||
Path: filepath.Join("/proc", strconv.Itoa(os.Getpid()), "exe"),
|
||||
Args: []string{"libnetwork-setkey", "-exec-root=" + iface.provider.Config().Daemon.ExecRoot, iface.sbx.ContainerID(), shortNetCtlrID},
|
||||
Args: []string{"libnetwork-setkey", "-exec-root=" + iface.provider.Config().ExecRoot, iface.sbx.ContainerID(), shortNetCtlrID},
|
||||
}},
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -109,7 +109,7 @@ func (cs *CachableSource) HandleChange(kind fsutil.ChangeKind, p string, fi os.F
|
||||
}
|
||||
|
||||
hfi := &fileInfo{
|
||||
sum: h.Digest().Hex(),
|
||||
sum: h.Digest().Encoded(),
|
||||
}
|
||||
cs.txn.Insert([]byte(p), hfi)
|
||||
cs.mu.Unlock()
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
package client // import "github.com/docker/docker/client"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
)
|
||||
|
||||
const containerWaitErrorMsgLimit = 2 * 1024 /* Max: 2KiB */
|
||||
|
||||
// ContainerWait waits until the specified container is in a certain state
|
||||
// indicated by the given condition, either "not-running" (default),
|
||||
// "next-exit", or "removed".
|
||||
@@ -46,9 +51,23 @@ func (cli *Client) ContainerWait(ctx context.Context, containerID string, condit
|
||||
|
||||
go func() {
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
body := resp.body
|
||||
responseText := bytes.NewBuffer(nil)
|
||||
stream := io.TeeReader(body, responseText)
|
||||
|
||||
var res container.WaitResponse
|
||||
if err := json.NewDecoder(resp.body).Decode(&res); err != nil {
|
||||
errC <- err
|
||||
if err := json.NewDecoder(stream).Decode(&res); err != nil {
|
||||
// NOTE(nicks): The /wait API does not work well with HTTP proxies.
|
||||
// At any time, the proxy could cut off the response stream.
|
||||
//
|
||||
// But because the HTTP status has already been written, the proxy's
|
||||
// only option is to write a plaintext error message.
|
||||
//
|
||||
// If there's a JSON parsing error, read the real error message
|
||||
// off the body and send it to the client.
|
||||
_, _ = io.ReadAll(io.LimitReader(stream, containerWaitErrorMsgLimit))
|
||||
errC <- errors.New(responseText.String())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,61 @@ func TestContainerWait(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerWaitProxyInterrupt(t *testing.T) {
|
||||
expectedURL := "/v1.30/containers/container_id/wait"
|
||||
msg := "copying response body from Docker: unexpected EOF"
|
||||
client := &Client{
|
||||
version: "1.30",
|
||||
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
||||
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
||||
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
||||
}
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(strings.NewReader(msg)),
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
resultC, errC := client.ContainerWait(context.Background(), "container_id", "")
|
||||
select {
|
||||
case err := <-errC:
|
||||
if !strings.Contains(err.Error(), msg) {
|
||||
t.Fatalf("Expected: %s, Actual: %s", msg, err.Error())
|
||||
}
|
||||
case result := <-resultC:
|
||||
t.Fatalf("Unexpected result: %v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerWaitProxyInterruptLong(t *testing.T) {
|
||||
expectedURL := "/v1.30/containers/container_id/wait"
|
||||
msg := strings.Repeat("x", containerWaitErrorMsgLimit*5)
|
||||
client := &Client{
|
||||
version: "1.30",
|
||||
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
||||
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
||||
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
||||
}
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(strings.NewReader(msg)),
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
resultC, errC := client.ContainerWait(context.Background(), "container_id", "")
|
||||
select {
|
||||
case err := <-errC:
|
||||
// LimitReader limiting isn't exact, because of how the Readers do chunking.
|
||||
if len(err.Error()) > containerWaitErrorMsgLimit*2 {
|
||||
t.Fatalf("Expected error to be limited around %d, actual length: %d", containerWaitErrorMsgLimit, len(err.Error()))
|
||||
}
|
||||
case result := <-resultC:
|
||||
t.Fatalf("Unexpected result: %v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleClient_ContainerWait_withTimeout() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -9,12 +9,13 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/docker/dockerversion"
|
||||
"github.com/ishidawataru/sctp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
f := os.NewFile(3, "signal-parent")
|
||||
host, container := parseHostContainerAddrs()
|
||||
host, container := parseFlags()
|
||||
|
||||
p, err := NewProxy(host, container)
|
||||
if err != nil {
|
||||
@@ -30,19 +31,26 @@ func main() {
|
||||
p.Run()
|
||||
}
|
||||
|
||||
// parseHostContainerAddrs parses the flags passed on reexec to create the TCP/UDP/SCTP
|
||||
// net.Addrs to map the host and container ports
|
||||
func parseHostContainerAddrs() (host net.Addr, container net.Addr) {
|
||||
// parseFlags parses the flags passed on reexec to create the TCP/UDP/SCTP
|
||||
// net.Addrs to map the host and container ports.
|
||||
func parseFlags() (host net.Addr, container net.Addr) {
|
||||
var (
|
||||
proto = flag.String("proto", "tcp", "proxy protocol")
|
||||
hostIP = flag.String("host-ip", "", "host ip")
|
||||
hostPort = flag.Int("host-port", -1, "host port")
|
||||
containerIP = flag.String("container-ip", "", "container ip")
|
||||
containerPort = flag.Int("container-port", -1, "container port")
|
||||
printVer = flag.Bool("v", false, "print version information and quit")
|
||||
printVersion = flag.Bool("version", false, "print version information and quit")
|
||||
)
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if *printVer || *printVersion {
|
||||
fmt.Printf("docker-proxy (commit %s) version %s\n", dockerversion.GitCommit, dockerversion.Version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
switch *proto {
|
||||
case "tcp":
|
||||
host = &net.TCPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort}
|
||||
|
||||
@@ -12,20 +12,6 @@ const defaultTrustKeyFile = "key.json"
|
||||
|
||||
// installCommonConfigFlags adds flags to the pflag.FlagSet to configure the daemon
|
||||
func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) error {
|
||||
var err error
|
||||
conf.Pidfile, err = getDefaultPidFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.Root, err = getDefaultDataRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.ExecRoot, err = getDefaultExecRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
allowNonDistributable = opts.NewNamedListOptsRef("allow-nondistributable-artifacts", &conf.AllowNondistributableArtifacts, registry.ValidateIndexName)
|
||||
registryMirrors = opts.NewNamedListOptsRef("registry-mirrors", &conf.Mirrors, registry.ValidateMirror)
|
||||
|
||||
@@ -5,18 +5,13 @@ package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/cgroups"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/homedir"
|
||||
"github.com/docker/docker/pkg/rootless"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/docker/rootless"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
@@ -27,12 +22,6 @@ func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) error {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.Ulimits = make(map[string]*units.Ulimit)
|
||||
|
||||
// Set default value for `--default-shm-size`
|
||||
conf.ShmSize = opts.MemBytes(config.DefaultShmSize)
|
||||
conf.Runtimes = make(map[string]types.Runtime)
|
||||
|
||||
// Then platform-specific install flags
|
||||
flags.Var(opts.NewNamedRuntimeOpt("runtimes", &conf.Runtimes, config.StockRuntimeName), "add-runtime", "Register an additional OCI compatible runtime")
|
||||
flags.StringVarP(&conf.SocketGroup, "group", "G", "docker", "Group for the unix socket")
|
||||
@@ -53,16 +42,7 @@ func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) error {
|
||||
flags.BoolVar(&conf.BridgeConfig.InterContainerCommunication, "icc", true, "Enable inter-container communication")
|
||||
flags.IPVar(&conf.BridgeConfig.DefaultIP, "ip", net.IPv4zero, "Default IP when binding container ports")
|
||||
flags.BoolVar(&conf.BridgeConfig.EnableUserlandProxy, "userland-proxy", true, "Use userland proxy for loopback traffic")
|
||||
defaultUserlandProxyPath := ""
|
||||
if rootless.RunningWithRootlessKit() {
|
||||
var err error
|
||||
// use rootlesskit-docker-proxy for exposing the ports in RootlessKit netns to the initial namespace.
|
||||
defaultUserlandProxyPath, err = exec.LookPath(rootless.RootlessKitDockerProxyBinary)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "running with RootlessKit, but %s not installed", rootless.RootlessKitDockerProxyBinary)
|
||||
}
|
||||
}
|
||||
flags.StringVar(&conf.BridgeConfig.UserlandProxyPath, "userland-proxy-path", defaultUserlandProxyPath, "Path to the userland proxy binary")
|
||||
flags.StringVar(&conf.BridgeConfig.UserlandProxyPath, "userland-proxy-path", conf.BridgeConfig.UserlandProxyPath, "Path to the userland proxy binary")
|
||||
flags.StringVar(&conf.CgroupParent, "cgroup-parent", "", "Set parent cgroup for all containers")
|
||||
flags.StringVar(&conf.RemappedRoot, "userns-remap", "", "User/Group setting for user namespaces")
|
||||
flags.BoolVar(&conf.LiveRestoreEnabled, "live-restore", false, "Enable live restore of docker when containers are still running")
|
||||
@@ -71,19 +51,15 @@ func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) error {
|
||||
flags.StringVar(&conf.InitPath, "init-path", "", "Path to the docker-init binary")
|
||||
flags.Int64Var(&conf.CPURealtimePeriod, "cpu-rt-period", 0, "Limit the CPU real-time period in microseconds for the parent cgroup for all containers (not supported with cgroups v2)")
|
||||
flags.Int64Var(&conf.CPURealtimeRuntime, "cpu-rt-runtime", 0, "Limit the CPU real-time runtime in microseconds for the parent cgroup for all containers (not supported with cgroups v2)")
|
||||
flags.StringVar(&conf.SeccompProfile, "seccomp-profile", config.SeccompProfileDefault, `Path to seccomp profile. Use "unconfined" to disable the default seccomp profile`)
|
||||
flags.StringVar(&conf.SeccompProfile, "seccomp-profile", conf.SeccompProfile, `Path to seccomp profile. Use "unconfined" to disable the default seccomp profile`)
|
||||
flags.Var(&conf.ShmSize, "default-shm-size", "Default shm size for containers")
|
||||
flags.BoolVar(&conf.NoNewPrivileges, "no-new-privileges", false, "Set no-new-privileges by default for new containers")
|
||||
flags.StringVar(&conf.IpcMode, "default-ipc-mode", string(config.DefaultIpcMode), `Default mode for containers ipc ("shareable" | "private")`)
|
||||
flags.StringVar(&conf.IpcMode, "default-ipc-mode", conf.IpcMode, `Default mode for containers ipc ("shareable" | "private")`)
|
||||
flags.Var(&conf.NetworkConfig.DefaultAddressPools, "default-address-pool", "Default address pools for node specific local networks")
|
||||
// rootless needs to be explicitly specified for running "rootful" dockerd in rootless dockerd (#38702)
|
||||
// Note that defaultUserlandProxyPath and honorXDG are configured according to the value of rootless.RunningWithRootlessKit, not the value of --rootless.
|
||||
flags.BoolVar(&conf.Rootless, "rootless", rootless.RunningWithRootlessKit(), "Enable rootless mode; typically used with RootlessKit")
|
||||
defaultCgroupNamespaceMode := config.DefaultCgroupNamespaceMode
|
||||
if cgroups.Mode() != cgroups.Unified {
|
||||
defaultCgroupNamespaceMode = config.DefaultCgroupV1NamespaceMode
|
||||
}
|
||||
flags.StringVar(&conf.CgroupNamespaceMode, "default-cgroupns-mode", string(defaultCgroupNamespaceMode), `Default mode for containers cgroup namespace ("host" | "private")`)
|
||||
// Note that conf.BridgeConfig.UserlandProxyPath and honorXDG are configured according to the value of rootless.RunningWithRootlessKit, not the value of --rootless.
|
||||
flags.BoolVar(&conf.Rootless, "rootless", conf.Rootless, "Enable rootless mode; typically used with RootlessKit")
|
||||
flags.StringVar(&conf.CgroupNamespaceMode, "default-cgroupns-mode", conf.CgroupNamespaceMode, `Default mode for containers cgroup namespace ("host" | "private")`)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -97,36 +73,3 @@ func configureCertsDir() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getDefaultPidFile() (string, error) {
|
||||
if !honorXDG {
|
||||
return "/var/run/docker.pid", nil
|
||||
}
|
||||
runtimeDir, err := homedir.GetRuntimeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(runtimeDir, "docker.pid"), nil
|
||||
}
|
||||
|
||||
func getDefaultDataRoot() (string, error) {
|
||||
if !honorXDG {
|
||||
return "/var/lib/docker", nil
|
||||
}
|
||||
dataHome, err := homedir.GetDataHome()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(dataHome, "docker"), nil
|
||||
}
|
||||
|
||||
func getDefaultExecRoot() (string, error) {
|
||||
if !honorXDG {
|
||||
return "/var/run/docker", nil
|
||||
}
|
||||
runtimeDir, err := homedir.GetRuntimeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(runtimeDir, "docker"), nil
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@ import (
|
||||
func TestDaemonParseShmSize(t *testing.T) {
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
conf := &config.Config{}
|
||||
err := installConfigFlags(conf, flags)
|
||||
conf, err := config.New()
|
||||
assert.NilError(t, err)
|
||||
err = installConfigFlags(conf, flags)
|
||||
assert.NilError(t, err)
|
||||
// By default `--default-shm-size=64M`
|
||||
assert.Check(t, is.Equal(int64(64*1024*1024), conf.ShmSize.Value()))
|
||||
|
||||
@@ -1,25 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/daemon/config"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func getDefaultPidFile() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func getDefaultDataRoot() (string, error) {
|
||||
return filepath.Join(os.Getenv("programdata"), "docker"), nil
|
||||
}
|
||||
|
||||
func getDefaultExecRoot() (string, error) {
|
||||
return filepath.Join(os.Getenv("programdata"), "docker", "exec-root"), nil
|
||||
}
|
||||
|
||||
// installConfigFlags adds flags to the pflag.FlagSet to configure the daemon
|
||||
func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) error {
|
||||
// First handle install flags which are consistent cross-platform
|
||||
|
||||
@@ -46,10 +46,10 @@ import (
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/pkg/pidfile"
|
||||
"github.com/docker/docker/pkg/plugingetter"
|
||||
"github.com/docker/docker/pkg/rootless"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/docker/plugin"
|
||||
"github.com/docker/docker/rootless"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/moby/buildkit/session"
|
||||
|
||||
@@ -24,7 +24,7 @@ func setDefaultUmask() error {
|
||||
}
|
||||
|
||||
func getDaemonConfDir(root string) (string, error) {
|
||||
return filepath.Join(root, `\config`), nil
|
||||
return filepath.Join(root, "config"), nil
|
||||
}
|
||||
|
||||
// preNotifyReady sends a message to the host when the API is active, but before the daemon is
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/docker/docker/dockerversion"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
"github.com/docker/docker/rootless"
|
||||
"github.com/docker/docker/pkg/rootless"
|
||||
"github.com/moby/buildkit/util/apicaps"
|
||||
"github.com/moby/term"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -21,7 +21,11 @@ var (
|
||||
)
|
||||
|
||||
func newDaemonCommand() (*cobra.Command, error) {
|
||||
opts := newDaemonOptions(config.New())
|
||||
cfg, err := config.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts := newDaemonOptions(cfg)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "dockerd [OPTIONS]",
|
||||
|
||||
@@ -24,7 +24,7 @@ func runDaemon(opts *daemonOptions) error {
|
||||
|
||||
// Windows specific settings as these are not defaulted.
|
||||
if opts.configFile == "" {
|
||||
opts.configFile = filepath.Join(opts.daemonConfig.Root, `config\daemon.json`)
|
||||
opts.configFile = filepath.Join(opts.daemonConfig.Root, "config", "daemon.json")
|
||||
}
|
||||
if runAsService {
|
||||
// If Windows SCM manages the service - no need for PID files
|
||||
|
||||
@@ -65,8 +65,6 @@ func (o *daemonOptions) installFlags(flags *pflag.FlagSet) {
|
||||
flags.BoolVar(&o.TLS, FlagTLS, DefaultTLSValue, "Use TLS; implied by --tlsverify")
|
||||
flags.BoolVar(&o.TLSVerify, FlagTLSVerify, dockerTLSVerify || DefaultTLSValue, "Use TLS and verify the remote")
|
||||
|
||||
// TODO use flag flags.String("identity"}, "i", "", "Path to libtrust key file")
|
||||
|
||||
o.TLSOptions = &tlsconfig.Options{}
|
||||
tlsOptions := o.TLSOptions
|
||||
flags.StringVar(&tlsOptions.CAFile, "tlscacert", filepath.Join(dockerCertPath, DefaultCaFile), "Trust certs signed only by this CA")
|
||||
|
||||
@@ -3,11 +3,9 @@ package trap // import "github.com/docker/docker/cmd/dockerd/trap"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
gosignal "os/signal"
|
||||
"os/signal"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/docker/pkg/stack"
|
||||
)
|
||||
|
||||
// Trap sets up a simplified signal "trap", appropriate for common
|
||||
@@ -17,7 +15,6 @@ import (
|
||||
// - If SIGINT or SIGTERM are received, `cleanup` is called, then the process is terminated.
|
||||
// - If SIGINT or SIGTERM are received 3 times before cleanup is complete, then cleanup is
|
||||
// skipped and the process is terminated immediately (allows force quit of stuck daemon)
|
||||
// - A SIGQUIT always causes an exit without cleanup, with a goroutine dump preceding exit.
|
||||
// - Ignore SIGPIPE events. These are generated by systemd when journald is restarted while
|
||||
// the docker daemon is not restarted and also running under systemd.
|
||||
// Fixes https://github.com/docker/docker/issues/19728
|
||||
@@ -25,9 +22,8 @@ func Trap(cleanup func(), logger interface {
|
||||
Info(args ...interface{})
|
||||
}) {
|
||||
c := make(chan os.Signal, 1)
|
||||
// we will handle INT, TERM, QUIT, SIGPIPE here
|
||||
signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGPIPE}
|
||||
gosignal.Notify(c, signals...)
|
||||
// we will handle INT, TERM, SIGPIPE here
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGPIPE)
|
||||
go func() {
|
||||
interruptCount := uint32(0)
|
||||
for sig := range c {
|
||||
@@ -52,11 +48,8 @@ func Trap(cleanup func(), logger interface {
|
||||
// 3 SIGTERM/INT signals received; force exit without cleanup
|
||||
logger.Info("Forcing docker daemon shutdown without cleanup; 3 interrupts received")
|
||||
}
|
||||
case syscall.SIGQUIT:
|
||||
stack.Dump()
|
||||
logger.Info("Forcing docker daemon shutdown without cleanup on SIGQUIT")
|
||||
}
|
||||
// for the SIGINT/TERM, and SIGQUIT non-clean shutdown case, exit with 128 + signal #
|
||||
// for the SIGINT/TERM non-clean shutdown case, exit with 128 + signal #
|
||||
os.Exit(128 + int(sig.(syscall.Signal)))
|
||||
}(sig)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ func TestTrap(t *testing.T) {
|
||||
multiple bool
|
||||
}{
|
||||
{"TERM", syscall.SIGTERM, false},
|
||||
{"QUIT", syscall.SIGQUIT, true},
|
||||
{"INT", os.Interrupt, false},
|
||||
{"TERM", syscall.SIGTERM, true},
|
||||
{"INT", os.Interrupt, true},
|
||||
|
||||
@@ -11,6 +11,10 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
"golang.org/x/text/transform"
|
||||
|
||||
"github.com/containerd/containerd/runtime/v2/shim"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/authorization"
|
||||
@@ -294,9 +298,10 @@ func (conf *Config) IsValueSet(name string) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// New returns a new fully initialized Config struct
|
||||
func New() *Config {
|
||||
return &Config{
|
||||
// New returns a new fully initialized Config struct with default values set.
|
||||
func New() (*Config, error) {
|
||||
// platform-agnostic default values for the Config.
|
||||
cfg := &Config{
|
||||
CommonConfig: CommonConfig{
|
||||
ShutdownTimeout: DefaultShutdownTimeout,
|
||||
LogConfig: LogConfig{
|
||||
@@ -314,6 +319,12 @@ func New() *Config {
|
||||
DefaultRuntime: StockRuntimeName,
|
||||
},
|
||||
}
|
||||
|
||||
if err := setPlatformDefaults(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// GetConflictFreeLabels validates Labels for conflict
|
||||
@@ -348,7 +359,10 @@ func Reload(configFile string, flags *pflag.FlagSet, reload func(*Config)) error
|
||||
if flags.Changed("config-file") || !os.IsNotExist(err) {
|
||||
return errors.Wrapf(err, "unable to configure the Docker daemon with file %s", configFile)
|
||||
}
|
||||
newConfig = New()
|
||||
newConfig, err = New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Check if duplicate label-keys with different values are found
|
||||
@@ -424,12 +438,41 @@ func getConflictFreeConfiguration(configFile string, flags *pflag.FlagSet) (*Con
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config Config
|
||||
|
||||
// Decode the contents of the JSON file using a [byte order mark] if present, instead of assuming UTF-8 without BOM.
|
||||
// The BOM, if present, will be used to determine the encoding. If no BOM is present, we will assume the default
|
||||
// and preferred encoding for JSON as defined by [RFC 8259], UTF-8 without BOM.
|
||||
//
|
||||
// While JSON is normatively UTF-8 with no BOM, there are a couple of reasons to decode here:
|
||||
// * UTF-8 with BOM is something that new implementations should avoid producing; however, [RFC 8259 Section 8.1]
|
||||
// allows implementations to ignore the UTF-8 BOM when present for interoperability. Older versions of Notepad,
|
||||
// the only text editor available out of the box on Windows Server, writes UTF-8 with a BOM by default.
|
||||
// * The default encoding for [Windows PowerShell] is UTF-16 LE with BOM. While encodings in PowerShell can be a
|
||||
// bit idiosyncratic, BOMs are still generally written. There is no support for selecting UTF-8 without a BOM as
|
||||
// the encoding in Windows PowerShell, though some Cmdlets only write UTF-8 with no BOM. PowerShell Core
|
||||
// introduces `utf8NoBOM` and makes it the default, but PowerShell Core is unlikely to be the implementation for
|
||||
// a majority of Windows Server + PowerShell users.
|
||||
// * While [RFC 8259 Section 8.1] asserts that software that is not part of a closed ecosystem or that crosses a
|
||||
// network boundary should only support UTF-8, and should never write a BOM, it does acknowledge older versions
|
||||
// of the standard, such as [RFC 7159 Section 8.1]. In the interest of pragmatism and easing pain for Windows
|
||||
// users, we consider Windows tools such as Windows PowerShell and Notepad part of our ecosystem, and support
|
||||
// the two most common encodings: UTF-16 LE with BOM, and UTF-8 with BOM, in addition to the standard UTF-8
|
||||
// without BOM.
|
||||
//
|
||||
// [byte order mark]: https://www.unicode.org/faq/utf_bom.html#BOM
|
||||
// [RFC 8259]: https://www.rfc-editor.org/rfc/rfc8259
|
||||
// [RFC 8259 Section 8.1]: https://www.rfc-editor.org/rfc/rfc8259#section-8.1
|
||||
// [RFC 7159 Section 8.1]: https://www.rfc-editor.org/rfc/rfc7159#section-8.1
|
||||
// [Windows PowerShell]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_character_encoding?view=powershell-5.1
|
||||
b, n, err := transform.Bytes(transform.Chain(unicode.BOMOverride(transform.Nop), encoding.UTF8Validator), b)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to decode configuration JSON at offset %d", n)
|
||||
}
|
||||
// Trim whitespace so that an empty config can be detected for an early return.
|
||||
b = bytes.TrimSpace(b)
|
||||
|
||||
var config Config
|
||||
if len(b) == 0 {
|
||||
// empty config file
|
||||
return &config, nil
|
||||
return &config, nil // early return on empty config
|
||||
}
|
||||
|
||||
if flags != nil {
|
||||
|
||||
@@ -3,11 +3,17 @@ package config // import "github.com/docker/docker/daemon/config"
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/cgroups"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/homedir"
|
||||
"github.com/docker/docker/pkg/rootless"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -161,3 +167,47 @@ func (conf *Config) ValidatePlatformConfig() error {
|
||||
func (conf *Config) IsRootless() bool {
|
||||
return conf.Rootless
|
||||
}
|
||||
|
||||
func setPlatformDefaults(cfg *Config) error {
|
||||
cfg.Ulimits = make(map[string]*units.Ulimit)
|
||||
cfg.ShmSize = opts.MemBytes(DefaultShmSize)
|
||||
cfg.SeccompProfile = SeccompProfileDefault
|
||||
cfg.IpcMode = string(DefaultIpcMode)
|
||||
cfg.Runtimes = make(map[string]types.Runtime)
|
||||
|
||||
if cgroups.Mode() != cgroups.Unified {
|
||||
cfg.CgroupNamespaceMode = string(DefaultCgroupV1NamespaceMode)
|
||||
} else {
|
||||
cfg.CgroupNamespaceMode = string(DefaultCgroupNamespaceMode)
|
||||
}
|
||||
|
||||
if rootless.RunningWithRootlessKit() {
|
||||
cfg.Rootless = true
|
||||
|
||||
var err error
|
||||
// use rootlesskit-docker-proxy for exposing the ports in RootlessKit netns to the initial namespace.
|
||||
cfg.BridgeConfig.UserlandProxyPath, err = exec.LookPath(rootless.RootlessKitDockerProxyBinary)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "running with RootlessKit, but %s not installed", rootless.RootlessKitDockerProxyBinary)
|
||||
}
|
||||
|
||||
dataHome, err := homedir.GetDataHome()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runtimeDir, err := homedir.GetRuntimeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg.Root = filepath.Join(dataHome, "docker")
|
||||
cfg.ExecRoot = filepath.Join(runtimeDir, "docker")
|
||||
cfg.Pidfile = filepath.Join(runtimeDir, "docker.pid")
|
||||
} else {
|
||||
cfg.Root = "/var/lib/docker"
|
||||
cfg.ExecRoot = "/var/run/docker"
|
||||
cfg.Pidfile = "/var/run/docker.pid"
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -9,11 +9,10 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/fs"
|
||||
)
|
||||
|
||||
func TestGetConflictFreeConfiguration(t *testing.T) {
|
||||
configFileData := `
|
||||
configFile := makeConfigFile(t, `
|
||||
{
|
||||
"debug": true,
|
||||
"default-ulimits": {
|
||||
@@ -26,10 +25,7 @@ func TestGetConflictFreeConfiguration(t *testing.T) {
|
||||
"log-opts": {
|
||||
"tag": "test_tag"
|
||||
}
|
||||
}`
|
||||
|
||||
file := fs.NewFile(t, "docker-config", fs.WithContent(configFileData))
|
||||
defer file.Remove()
|
||||
}`)
|
||||
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
var debug bool
|
||||
@@ -37,7 +33,7 @@ func TestGetConflictFreeConfiguration(t *testing.T) {
|
||||
flags.Var(opts.NewNamedUlimitOpt("default-ulimits", nil), "default-ulimit", "")
|
||||
flags.Var(opts.NewNamedMapOpts("log-opts", nil, nil), "log-opt", "")
|
||||
|
||||
cc, err := getConflictFreeConfiguration(file.Path(), flags)
|
||||
cc, err := getConflictFreeConfiguration(configFile, flags)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, cc.Debug)
|
||||
@@ -54,7 +50,7 @@ func TestGetConflictFreeConfiguration(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDaemonConfigurationMerge(t *testing.T) {
|
||||
configFileData := `
|
||||
configFile := makeConfigFile(t, `
|
||||
{
|
||||
"debug": true,
|
||||
"default-ulimits": {
|
||||
@@ -64,12 +60,10 @@ func TestDaemonConfigurationMerge(t *testing.T) {
|
||||
"Soft": 1024
|
||||
}
|
||||
}
|
||||
}`
|
||||
}`)
|
||||
|
||||
file := fs.NewFile(t, "docker-config", fs.WithContent(configFileData))
|
||||
defer file.Remove()
|
||||
|
||||
conf := New()
|
||||
conf, err := New()
|
||||
assert.NilError(t, err)
|
||||
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
flags.BoolVarP(&conf.Debug, "debug", "D", false, "")
|
||||
@@ -81,7 +75,7 @@ func TestDaemonConfigurationMerge(t *testing.T) {
|
||||
assert.Check(t, flags.Set("log-driver", "syslog"))
|
||||
assert.Check(t, flags.Set("log-opt", "tag=from_flag"))
|
||||
|
||||
cc, err := MergeDaemonConfigurations(conf, flags, file.Path())
|
||||
cc, err := MergeDaemonConfigurations(conf, flags, configFile)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, cc.Debug)
|
||||
@@ -106,10 +100,7 @@ func TestDaemonConfigurationMerge(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDaemonConfigurationMergeShmSize(t *testing.T) {
|
||||
data := `{"default-shm-size": "1g"}`
|
||||
|
||||
file := fs.NewFile(t, "docker-config", fs.WithContent(data))
|
||||
defer file.Remove()
|
||||
configFile := makeConfigFile(t, `{"default-shm-size": "1g"}`)
|
||||
|
||||
c := &Config{}
|
||||
|
||||
@@ -117,7 +108,7 @@ func TestDaemonConfigurationMergeShmSize(t *testing.T) {
|
||||
shmSize := opts.MemBytes(DefaultShmSize)
|
||||
flags.Var(&shmSize, "default-shm-size", "")
|
||||
|
||||
cc, err := MergeDaemonConfigurations(c, flags, file.Path())
|
||||
cc, err := MergeDaemonConfigurations(c, flags, configFile)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expectedValue := 1 * 1024 * 1024 * 1024
|
||||
|
||||
@@ -2,6 +2,7 @@ package config // import "github.com/docker/docker/daemon/config"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -12,29 +13,82 @@ import (
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/spf13/pflag"
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/fs"
|
||||
"gotest.tools/v3/skip"
|
||||
)
|
||||
|
||||
func makeConfigFile(t *testing.T, content string) string {
|
||||
t.Helper()
|
||||
name := filepath.Join(t.TempDir(), "daemon.json")
|
||||
err := os.WriteFile(name, []byte(content), 0666)
|
||||
assert.NilError(t, err)
|
||||
return name
|
||||
}
|
||||
|
||||
func TestDaemonConfigurationNotFound(t *testing.T) {
|
||||
_, err := MergeDaemonConfigurations(&Config{}, nil, "/tmp/foo-bar-baz-docker")
|
||||
assert.Check(t, os.IsNotExist(err), "got: %[1]T: %[1]v", err)
|
||||
}
|
||||
|
||||
func TestDaemonBrokenConfiguration(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "docker-config-")
|
||||
assert.NilError(t, err)
|
||||
configFile := makeConfigFile(t, `{"Debug": tru`)
|
||||
|
||||
configFile := f.Name()
|
||||
f.Write([]byte(`{"Debug": tru`))
|
||||
f.Close()
|
||||
|
||||
_, err = MergeDaemonConfigurations(&Config{}, nil, configFile)
|
||||
_, err := MergeDaemonConfigurations(&Config{}, nil, configFile)
|
||||
assert.ErrorContains(t, err, `invalid character ' ' in literal true`)
|
||||
}
|
||||
|
||||
// TestDaemonConfigurationUnicodeVariations feeds various variations of Unicode into the JSON parser, ensuring that we
|
||||
// respect a BOM and otherwise default to UTF-8.
|
||||
func TestDaemonConfigurationUnicodeVariations(t *testing.T) {
|
||||
jsonData := `{"debug": true}`
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
encoding encoding.Encoding
|
||||
}{
|
||||
{
|
||||
name: "UTF-8",
|
||||
encoding: unicode.UTF8,
|
||||
},
|
||||
{
|
||||
name: "UTF-8 (with BOM)",
|
||||
encoding: unicode.UTF8BOM,
|
||||
},
|
||||
{
|
||||
name: "UTF-16 (BE with BOM)",
|
||||
encoding: unicode.UTF16(unicode.BigEndian, unicode.UseBOM),
|
||||
},
|
||||
{
|
||||
name: "UTF-16 (LE with BOM)",
|
||||
encoding: unicode.UTF16(unicode.LittleEndian, unicode.UseBOM),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
encodedJson, err := tc.encoding.NewEncoder().String(jsonData)
|
||||
assert.NilError(t, err)
|
||||
configFile := makeConfigFile(t, encodedJson)
|
||||
_, err = MergeDaemonConfigurations(&Config{}, nil, configFile)
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestDaemonConfigurationInvalidUnicode ensures that the JSON parser returns a useful error message if malformed UTF-8
|
||||
// is provided.
|
||||
func TestDaemonConfigurationInvalidUnicode(t *testing.T) {
|
||||
configFileBOM := makeConfigFile(t, "\xef\xbb\xbf{\"debug\": true}\xff")
|
||||
_, err := MergeDaemonConfigurations(&Config{}, nil, configFileBOM)
|
||||
assert.ErrorIs(t, err, encoding.ErrInvalidUTF8)
|
||||
|
||||
configFileNoBOM := makeConfigFile(t, "{\"debug\": true}\xff")
|
||||
_, err = MergeDaemonConfigurations(&Config{}, nil, configFileNoBOM)
|
||||
assert.ErrorIs(t, err, encoding.ErrInvalidUTF8)
|
||||
}
|
||||
|
||||
func TestFindConfigurationConflicts(t *testing.T) {
|
||||
config := map[string]interface{}{"authorization-plugins": "foobar"}
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
@@ -56,18 +110,13 @@ func TestFindConfigurationConflictsWithNamedOptions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDaemonConfigurationMergeConflicts(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "docker-config-")
|
||||
assert.NilError(t, err)
|
||||
|
||||
configFile := f.Name()
|
||||
f.Write([]byte(`{"debug": true}`))
|
||||
f.Close()
|
||||
configFile := makeConfigFile(t, `{"debug": true}`)
|
||||
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
flags.Bool("debug", false, "")
|
||||
assert.Check(t, flags.Set("debug", "false"))
|
||||
|
||||
_, err = MergeDaemonConfigurations(&Config{}, flags, configFile)
|
||||
_, err := MergeDaemonConfigurations(&Config{}, flags, configFile)
|
||||
if err == nil {
|
||||
t.Fatal("expected error, got nil")
|
||||
}
|
||||
@@ -77,51 +126,34 @@ func TestDaemonConfigurationMergeConflicts(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDaemonConfigurationMergeConcurrent(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "docker-config-")
|
||||
assert.NilError(t, err)
|
||||
configFile := makeConfigFile(t, `{"max-concurrent-downloads": 1}`)
|
||||
|
||||
configFile := f.Name()
|
||||
f.Write([]byte(`{"max-concurrent-downloads": 1}`))
|
||||
f.Close()
|
||||
|
||||
_, err = MergeDaemonConfigurations(&Config{}, nil, configFile)
|
||||
_, err := MergeDaemonConfigurations(&Config{}, nil, configFile)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestDaemonConfigurationMergeConcurrentError(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "docker-config-")
|
||||
assert.NilError(t, err)
|
||||
configFile := makeConfigFile(t, `{"max-concurrent-downloads": -1}`)
|
||||
|
||||
configFile := f.Name()
|
||||
f.Write([]byte(`{"max-concurrent-downloads": -1}`))
|
||||
f.Close()
|
||||
|
||||
_, err = MergeDaemonConfigurations(&Config{}, nil, configFile)
|
||||
_, err := MergeDaemonConfigurations(&Config{}, nil, configFile)
|
||||
assert.ErrorContains(t, err, `invalid max concurrent downloads: -1`)
|
||||
}
|
||||
|
||||
func TestDaemonConfigurationMergeConflictsWithInnerStructs(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "docker-config-")
|
||||
assert.NilError(t, err)
|
||||
|
||||
configFile := f.Name()
|
||||
f.Write([]byte(`{"tlscacert": "/etc/certificates/ca.pem"}`))
|
||||
f.Close()
|
||||
configFile := makeConfigFile(t, `{"tlscacert": "/etc/certificates/ca.pem"}`)
|
||||
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
flags.String("tlscacert", "", "")
|
||||
assert.Check(t, flags.Set("tlscacert", "~/.docker/ca.pem"))
|
||||
|
||||
_, err = MergeDaemonConfigurations(&Config{}, flags, configFile)
|
||||
_, err := MergeDaemonConfigurations(&Config{}, flags, configFile)
|
||||
assert.ErrorContains(t, err, `the following directives are specified both as a flag and in the configuration file: tlscacert`)
|
||||
}
|
||||
|
||||
// Test for #40711
|
||||
// TestDaemonConfigurationMergeDefaultAddressPools is a regression test for #40711.
|
||||
func TestDaemonConfigurationMergeDefaultAddressPools(t *testing.T) {
|
||||
emptyConfigFile := fs.NewFile(t, "config", fs.WithContent(`{}`))
|
||||
defer emptyConfigFile.Remove()
|
||||
configFile := fs.NewFile(t, "config", fs.WithContent(`{"default-address-pools":[{"base": "10.123.0.0/16", "size": 24 }]}`))
|
||||
defer configFile.Remove()
|
||||
emptyConfigFile := makeConfigFile(t, `{}`)
|
||||
configFile := makeConfigFile(t, `{"default-address-pools":[{"base": "10.123.0.0/16", "size": 24 }]}`)
|
||||
|
||||
expected := []*ipamutils.NetworkToSplit{{Base: "10.123.0.0/16", Size: 24}}
|
||||
|
||||
@@ -131,7 +163,7 @@ func TestDaemonConfigurationMergeDefaultAddressPools(t *testing.T) {
|
||||
flags.Var(&conf.NetworkConfig.DefaultAddressPools, "default-address-pool", "")
|
||||
assert.Check(t, flags.Set("default-address-pool", "base=10.123.0.0/16,size=24"))
|
||||
|
||||
config, err := MergeDaemonConfigurations(&conf, flags, emptyConfigFile.Path())
|
||||
config, err := MergeDaemonConfigurations(&conf, flags, emptyConfigFile)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, config.DefaultAddressPools.Value(), expected)
|
||||
})
|
||||
@@ -141,7 +173,7 @@ func TestDaemonConfigurationMergeDefaultAddressPools(t *testing.T) {
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
flags.Var(&conf.NetworkConfig.DefaultAddressPools, "default-address-pool", "")
|
||||
|
||||
config, err := MergeDaemonConfigurations(&conf, flags, configFile.Path())
|
||||
config, err := MergeDaemonConfigurations(&conf, flags, configFile)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, config.DefaultAddressPools.Value(), expected)
|
||||
})
|
||||
@@ -152,7 +184,7 @@ func TestDaemonConfigurationMergeDefaultAddressPools(t *testing.T) {
|
||||
flags.Var(&conf.NetworkConfig.DefaultAddressPools, "default-address-pool", "")
|
||||
assert.Check(t, flags.Set("default-address-pool", "base=10.123.0.0/16,size=24"))
|
||||
|
||||
_, err := MergeDaemonConfigurations(&conf, flags, configFile.Path())
|
||||
_, err := MergeDaemonConfigurations(&conf, flags, configFile)
|
||||
assert.ErrorContains(t, err, "the following directives are specified both as a flag and in the configuration file")
|
||||
assert.ErrorContains(t, err, "default-address-pools")
|
||||
})
|
||||
@@ -338,13 +370,14 @@ func TestValidateConfigurationErrors(t *testing.T) {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cfg := New()
|
||||
cfg, err := New()
|
||||
assert.NilError(t, err)
|
||||
if tc.field != "" {
|
||||
assert.Check(t, mergo.Merge(cfg, tc.config, mergo.WithOverride, withForceOverwrite(tc.field)))
|
||||
} else {
|
||||
assert.Check(t, mergo.Merge(cfg, tc.config, mergo.WithOverride))
|
||||
}
|
||||
err := Validate(cfg)
|
||||
err = Validate(cfg)
|
||||
assert.Error(t, err, tc.expectedErr)
|
||||
})
|
||||
}
|
||||
@@ -481,12 +514,13 @@ func TestValidateConfiguration(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Start with a config with all defaults set, so that we only
|
||||
cfg := New()
|
||||
cfg, err := New()
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, mergo.Merge(cfg, tc.config, mergo.WithOverride))
|
||||
|
||||
// Check that the override happened :)
|
||||
assert.Check(t, is.DeepEqual(cfg, tc.config, field(tc.field)))
|
||||
err := Validate(cfg)
|
||||
err = Validate(cfg)
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
}
|
||||
@@ -503,8 +537,8 @@ func field(field string) cmp.Option {
|
||||
return cmpopts.IgnoreFields(Config{}, ignoreFields...)
|
||||
}
|
||||
|
||||
// TestReloadSetConfigFileNotExist tests that when `--config-file` is set
|
||||
// and it doesn't exist the `Reload` function returns an error.
|
||||
// TestReloadSetConfigFileNotExist tests that when `--config-file` is set, and it doesn't exist the `Reload` function
|
||||
// returns an error.
|
||||
func TestReloadSetConfigFileNotExist(t *testing.T) {
|
||||
configFile := "/tmp/blabla/not/exists/config.json"
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
@@ -515,8 +549,8 @@ func TestReloadSetConfigFileNotExist(t *testing.T) {
|
||||
assert.Check(t, is.ErrorContains(err, "unable to configure the Docker daemon with file"))
|
||||
}
|
||||
|
||||
// TestReloadDefaultConfigNotExist tests that if the default configuration file
|
||||
// doesn't exist the daemon still will be reloaded.
|
||||
// TestReloadDefaultConfigNotExist tests that if the default configuration file doesn't exist the daemon still will
|
||||
// still be reloaded.
|
||||
func TestReloadDefaultConfigNotExist(t *testing.T) {
|
||||
skip.If(t, os.Getuid() != 0, "skipping test that requires root")
|
||||
defaultConfigFile := "/tmp/blabla/not/exists/daemon.json"
|
||||
@@ -530,20 +564,15 @@ func TestReloadDefaultConfigNotExist(t *testing.T) {
|
||||
assert.Check(t, reloaded)
|
||||
}
|
||||
|
||||
// TestReloadBadDefaultConfig tests that when `--config-file` is not set
|
||||
// and the default configuration file exists and is bad return an error
|
||||
// TestReloadBadDefaultConfig tests that when `--config-file` is not set and the default configuration file exists and
|
||||
// is bad, an error is returned.
|
||||
func TestReloadBadDefaultConfig(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "docker-config-")
|
||||
assert.NilError(t, err)
|
||||
|
||||
configFile := f.Name()
|
||||
f.Write([]byte(`{wrong: "configuration"}`))
|
||||
f.Close()
|
||||
configFile := makeConfigFile(t, `{wrong: "configuration"}`)
|
||||
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
flags.String("config-file", configFile, "")
|
||||
reloaded := false
|
||||
err = Reload(configFile, flags, func(c *Config) {
|
||||
err := Reload(configFile, flags, func(c *Config) {
|
||||
reloaded = true
|
||||
})
|
||||
assert.Check(t, is.ErrorContains(err, "unable to configure the Docker daemon with file"))
|
||||
@@ -551,9 +580,7 @@ func TestReloadBadDefaultConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReloadWithConflictingLabels(t *testing.T) {
|
||||
tempFile := fs.NewFile(t, "config", fs.WithContent(`{"labels":["foo=bar","foo=baz"]}`))
|
||||
defer tempFile.Remove()
|
||||
configFile := tempFile.Path()
|
||||
configFile := makeConfigFile(t, `{"labels": ["foo=bar", "foo=baz"]}`)
|
||||
|
||||
var lbls []string
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
@@ -568,9 +595,7 @@ func TestReloadWithConflictingLabels(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReloadWithDuplicateLabels(t *testing.T) {
|
||||
tempFile := fs.NewFile(t, "config", fs.WithContent(`{"labels":["foo=the-same","foo=the-same"]}`))
|
||||
defer tempFile.Remove()
|
||||
configFile := tempFile.Path()
|
||||
configFile := makeConfigFile(t, `{"labels": ["foo=the-same", "foo=the-same"]}`)
|
||||
|
||||
var lbls []string
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package config // import "github.com/docker/docker/daemon/config"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
)
|
||||
|
||||
@@ -61,3 +64,10 @@ func (conf *Config) ValidatePlatformConfig() error {
|
||||
func (conf *Config) IsRootless() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func setPlatformDefaults(cfg *Config) error {
|
||||
cfg.Root = filepath.Join(os.Getenv("programdata"), "docker")
|
||||
cfg.ExecRoot = filepath.Join(os.Getenv("programdata"), "docker", "exec-root")
|
||||
cfg.Pidfile = filepath.Join(cfg.Root, "docker.pid")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package config // import "github.com/docker/docker/daemon/config"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/opts"
|
||||
@@ -11,19 +10,13 @@ import (
|
||||
)
|
||||
|
||||
func TestDaemonConfigurationMerge(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "docker-config-")
|
||||
assert.NilError(t, err)
|
||||
|
||||
configFile := f.Name()
|
||||
|
||||
f.Write([]byte(`
|
||||
configFile := makeConfigFile(t, `
|
||||
{
|
||||
"debug": true
|
||||
}`))
|
||||
}`)
|
||||
|
||||
f.Close()
|
||||
|
||||
conf := New()
|
||||
conf, err := New()
|
||||
assert.NilError(t, err)
|
||||
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
flags.BoolVarP(&conf.Debug, "debug", "D", false, "")
|
||||
|
||||
@@ -57,7 +57,18 @@ func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, e
|
||||
}
|
||||
return nil, errdefs.System(indexError)
|
||||
}
|
||||
return daemon.containers.Get(containerID), nil
|
||||
ctr := daemon.containers.Get(containerID)
|
||||
if ctr == nil {
|
||||
// Updates to the daemon.containersReplica ViewDB are not atomic
|
||||
// or consistent w.r.t. the live daemon.containers Store so
|
||||
// while reaching this code path may be indicative of a bug,
|
||||
// it is not _necessarily_ the case.
|
||||
logrus.WithField("prefixOrName", prefixOrName).
|
||||
WithField("id", containerID).
|
||||
Debugf("daemon.GetContainer: container is known to daemon.containersReplica but not daemon.containers")
|
||||
return nil, containerNotFound(prefixOrName)
|
||||
}
|
||||
return ctr, nil
|
||||
}
|
||||
|
||||
// checkContainer make sure the specified container validates the specified conditions
|
||||
@@ -224,7 +235,7 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *
|
||||
|
||||
runconfig.SetDefaultNetModeIfBlank(hostConfig)
|
||||
container.HostConfig = hostConfig
|
||||
return container.CheckpointTo(daemon.containersReplica)
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyContainerSettings performs validation of the hostconfig and config
|
||||
|
||||
@@ -465,7 +465,7 @@ func (daemon *Daemon) updateContainerNetworkSettings(container *container.Contai
|
||||
|
||||
networkName := mode.NetworkName()
|
||||
if mode.IsDefault() {
|
||||
networkName = daemon.netController.Config().Daemon.DefaultNetwork
|
||||
networkName = daemon.netController.Config().DefaultNetwork
|
||||
}
|
||||
|
||||
if mode.IsUserDefined() {
|
||||
|
||||
@@ -1053,19 +1053,6 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
|
||||
ContentNamespace: config.ContainerdNamespace,
|
||||
}
|
||||
|
||||
// This is a temporary environment variables used in CI to allow pushing
|
||||
// manifest v2 schema 1 images to test-registries used for testing *pulling*
|
||||
// these images.
|
||||
if os.Getenv("DOCKER_ALLOW_SCHEMA1_PUSH_DONOTUSE") != "" {
|
||||
imgSvcConfig.TrustKey, err = loadOrCreateTrustKey(config.TrustKeyPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = system.MkdirAll(filepath.Join(config.Root, "trust"), 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// containerd is not currently supported with Windows.
|
||||
// So sometimes d.containerdCli will be nil
|
||||
// In that case we'll create a local content store... but otherwise we'll use containerd
|
||||
@@ -1368,7 +1355,6 @@ func (daemon *Daemon) networkOptions(pg plugingetter.PluginGetter, activeSandbox
|
||||
dd := runconfig.DefaultDaemonNetworkMode()
|
||||
|
||||
options = []nwconfig.Option{
|
||||
nwconfig.OptionExperimental(conf.Experimental),
|
||||
nwconfig.OptionDataDir(conf.Root),
|
||||
nwconfig.OptionExecRoot(conf.GetExecRoot()),
|
||||
nwconfig.OptionDefaultDriver(string(dd)),
|
||||
|
||||
@@ -1309,7 +1309,8 @@ func getUnmountOnShutdownPath(config *config.Config) string {
|
||||
return filepath.Join(config.ExecRoot, "unmount-on-shutdown")
|
||||
}
|
||||
|
||||
// registerLinks writes the links to a file.
|
||||
// registerLinks registers network links between container and other containers
|
||||
// with the daemon using the specification in hostConfig.
|
||||
func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
||||
if hostConfig == nil || hostConfig.NetworkMode.IsUserDefined() {
|
||||
return nil
|
||||
@@ -1353,10 +1354,7 @@ func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *
|
||||
}
|
||||
}
|
||||
|
||||
// After we load all the links into the daemon
|
||||
// set them to nil on the hostconfig
|
||||
_, err := container.WriteHostConfig()
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// conditionalMountOnStart is a platform specific helper function during the
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -209,8 +210,8 @@ func (a *Driver) Status() [][2]string {
|
||||
return [][2]string{
|
||||
{"Root Dir", a.rootPath()},
|
||||
{"Backing Filesystem", backingFs},
|
||||
{"Dirs", fmt.Sprintf("%d", len(ids))},
|
||||
{"Dirperm1 Supported", fmt.Sprintf("%v", useDirperm())},
|
||||
{"Dirs", strconv.Itoa(len(ids))},
|
||||
{"Dirperm1 Supported", strconv.FormatBool(useDirperm())},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@@ -659,8 +660,8 @@ func testMountMoreThan42Layers(t *testing.T, mountPath string) {
|
||||
for i := 1; i < 127; i++ {
|
||||
expected++
|
||||
var (
|
||||
parent = fmt.Sprintf("%d", i-1)
|
||||
current = fmt.Sprintf("%d", i)
|
||||
parent = strconv.Itoa(i - 1)
|
||||
current = strconv.Itoa(i)
|
||||
)
|
||||
|
||||
if parent == "0" {
|
||||
|
||||
@@ -5,9 +5,17 @@ package btrfs // import "github.com/docker/docker/daemon/graphdriver/btrfs"
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <btrfs/ioctl.h>
|
||||
#include <btrfs/ctree.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0)
|
||||
#error "Headers from kernel >= 4.12 are required to build with Btrfs support."
|
||||
#error "HINT: Set 'DOCKER_BUILDTAGS=exclude_graphdriver_btrfs' to build without Btrfs."
|
||||
#endif
|
||||
|
||||
#include <linux/btrfs.h>
|
||||
#include <linux/btrfs_tree.h>
|
||||
|
||||
static void set_name_btrfs_ioctl_vol_args_v2(struct btrfs_ioctl_vol_args_v2* btrfs_struct, const char* value) {
|
||||
snprintf(btrfs_struct->name, BTRFS_SUBVOL_NAME_MAX, "%s", value);
|
||||
@@ -147,18 +155,11 @@ func (d *Driver) String() string {
|
||||
return "btrfs"
|
||||
}
|
||||
|
||||
// Status returns current driver information in a two dimensional string array.
|
||||
// Output contains "Build Version" and "Library Version" of the btrfs libraries used.
|
||||
// Version information can be used to check compatibility with your kernel.
|
||||
// Status returns the status of the driver.
|
||||
func (d *Driver) Status() [][2]string {
|
||||
status := [][2]string{}
|
||||
if bv := btrfsBuildVersion(); bv != "-" {
|
||||
status = append(status, [2]string{"Build Version", bv})
|
||||
return [][2]string{
|
||||
{"Btrfs", ""},
|
||||
}
|
||||
if lv := btrfsLibVersion(); lv != -1 {
|
||||
status = append(status, [2]string{"Library Version", fmt.Sprintf("%d", lv)})
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
// GetMetadata returns empty metadata for this driver.
|
||||
@@ -238,7 +239,7 @@ func subvolSnapshot(src, dest, name string) error {
|
||||
|
||||
var cs = C.CString(name)
|
||||
C.set_name_btrfs_ioctl_vol_args_v2(&args, cs)
|
||||
C.free(unsafe.Pointer(cs))
|
||||
free(cs)
|
||||
|
||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(destDir), C.BTRFS_IOC_SNAP_CREATE_V2,
|
||||
uintptr(unsafe.Pointer(&args)))
|
||||
@@ -395,7 +396,7 @@ func subvolLimitQgroup(path string, size uint64) error {
|
||||
defer closeDir(dir)
|
||||
|
||||
var args C.struct_btrfs_ioctl_qgroup_limit_args
|
||||
args.lim.max_referenced = C.__u64(size)
|
||||
args.lim.max_rfer = C.__u64(size)
|
||||
args.lim.flags = C.BTRFS_QGROUP_LIMIT_MAX_RFER
|
||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_QGROUP_LIMIT,
|
||||
uintptr(unsafe.Pointer(&args)))
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package btrfs // import "github.com/docker/docker/daemon/graphdriver/btrfs"
|
||||
|
||||
/*
|
||||
#include <btrfs/version.h>
|
||||
|
||||
// around version 3.16, they did not define lib version yet
|
||||
#ifndef BTRFS_LIB_VERSION
|
||||
#define BTRFS_LIB_VERSION -1
|
||||
#endif
|
||||
|
||||
// upstream had removed it, but now it will be coming back
|
||||
#ifndef BTRFS_BUILD_VERSION
|
||||
#define BTRFS_BUILD_VERSION "-"
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func btrfsBuildVersion() string {
|
||||
return string(C.BTRFS_BUILD_VERSION)
|
||||
}
|
||||
|
||||
func btrfsLibVersion() int {
|
||||
return int(C.BTRFS_LIB_VERSION)
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package btrfs // import "github.com/docker/docker/daemon/graphdriver/btrfs"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLibVersion(t *testing.T) {
|
||||
if btrfsLibVersion() <= 0 {
|
||||
t.Error("expected output from btrfs lib version > 0")
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/daemon/graphdriver"
|
||||
"github.com/docker/docker/dockerversion"
|
||||
"github.com/docker/docker/pkg/devicemapper"
|
||||
"github.com/docker/docker/pkg/dmesg"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
@@ -1672,12 +1671,7 @@ func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) {
|
||||
|
||||
// https://github.com/docker/docker/issues/4036
|
||||
if supported := devicemapper.UdevSetSyncSupport(true); !supported {
|
||||
if dockerversion.IAmStatic == "true" {
|
||||
logger.Error("Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a dynamic binary to use devicemapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/dockerd/#storage-driver-options")
|
||||
} else {
|
||||
logger.Error("Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a more recent version of libdevmapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/dockerd/#storage-driver-options")
|
||||
}
|
||||
|
||||
logger.Error("Udev sync is not supported, which will lead to data loss and unexpected behavior. Make sure you have a recent version of libdevmapper installed and are running a dynamic binary, or select a different storage driver. For more information, see https://docs.docker.com/go/storage-driver/")
|
||||
if !devices.overrideUdevSyncCheck {
|
||||
return graphdriver.ErrNotSupported
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) {
|
||||
}
|
||||
|
||||
func (d *Driver) cloneFilesystem(name, parentName string) error {
|
||||
snapshotName := fmt.Sprintf("%d", time.Now().Nanosecond())
|
||||
snapshotName := strconv.Itoa(time.Now().Nanosecond())
|
||||
parentDataset := zfs.Dataset{Name: parentName}
|
||||
snapshot, err := parentDataset.Snapshot(snapshotName /*recursive */, false)
|
||||
if err != nil {
|
||||
|
||||
@@ -127,7 +127,7 @@ deleteImagesLoop:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hex := id.Digest().Hex()
|
||||
hex := id.Digest().Encoded()
|
||||
imgDel, err := i.ImageDelete(hex, false, true)
|
||||
if imageDeleteFailed(hex, err) {
|
||||
continue
|
||||
|
||||
@@ -54,7 +54,6 @@ func (i *ImageService) PushImage(ctx context.Context, image, tag string, metaHea
|
||||
},
|
||||
ConfigMediaType: schema2.MediaTypeImageConfig,
|
||||
LayerStores: distribution.NewLayerProvidersFromStore(i.layerStore),
|
||||
TrustKey: i.trustKey,
|
||||
UploadManager: i.uploadManager,
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/docker/docker/layer"
|
||||
dockerreference "github.com/docker/docker/reference"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/libtrust"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/singleflight"
|
||||
@@ -44,7 +43,6 @@ type ImageServiceConfig struct {
|
||||
MaxDownloadAttempts int
|
||||
ReferenceStore dockerreference.Store
|
||||
RegistryService registry.Service
|
||||
TrustKey libtrust.PrivateKey
|
||||
ContentStore content.Store
|
||||
Leases leases.Manager
|
||||
ContentNamespace string
|
||||
@@ -61,7 +59,6 @@ func NewImageService(config ImageServiceConfig) *ImageService {
|
||||
layerStore: config.LayerStore,
|
||||
referenceStore: config.ReferenceStore,
|
||||
registryService: config.RegistryService,
|
||||
trustKey: config.TrustKey,
|
||||
uploadManager: xfer.NewLayerUploadManager(config.MaxConcurrentUploads),
|
||||
leases: config.Leases,
|
||||
content: config.ContentStore,
|
||||
@@ -80,7 +77,6 @@ type ImageService struct {
|
||||
pruneRunning int32
|
||||
referenceStore dockerreference.Store
|
||||
registryService registry.Service
|
||||
trustKey libtrust.PrivateKey
|
||||
uploadManager *xfer.LayerUploadManager
|
||||
leases leases.Manager
|
||||
content content.Store
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"go.etcd.io/bbolt"
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/assert/cmp"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func setupTestStores(t *testing.T) (context.Context, content.Store, *imageStoreWithLease, func(t *testing.T)) {
|
||||
@@ -75,24 +75,24 @@ func TestImageDelete(t *testing.T) {
|
||||
|
||||
ls, err := images.leases.List(ctx)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, cmp.Equal(len(ls), 1), ls)
|
||||
assert.Check(t, is.Equal(len(ls), 1), ls)
|
||||
|
||||
_, err = images.Delete(id)
|
||||
assert.NilError(t, err)
|
||||
|
||||
ls, err = images.leases.List(ctx)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, cmp.Equal(len(ls), 0), ls)
|
||||
assert.Check(t, is.Equal(len(ls), 0), ls)
|
||||
})
|
||||
}
|
||||
|
||||
func TestContentStoreForPull(t *testing.T) {
|
||||
ctx, cs, is, cleanup := setupTestStores(t)
|
||||
ctx, cs, imgStore, cleanup := setupTestStores(t)
|
||||
defer cleanup(t)
|
||||
|
||||
csP := &contentStoreForPull{
|
||||
ContentStore: cs,
|
||||
leases: is.leases,
|
||||
leases: imgStore.leases,
|
||||
}
|
||||
|
||||
data := []byte(`{}`)
|
||||
@@ -112,12 +112,12 @@ func TestContentStoreForPull(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, len(csP.digested), 1)
|
||||
assert.Check(t, cmp.Equal(csP.digested[0], desc.Digest))
|
||||
assert.Check(t, is.Equal(csP.digested[0], desc.Digest))
|
||||
|
||||
// Test already exists
|
||||
csP.digested = nil
|
||||
_, err = csP.Writer(ctx, content.WithRef(t.Name()), content.WithDescriptor(desc))
|
||||
assert.Check(t, c8derrdefs.IsAlreadyExists(err))
|
||||
assert.Equal(t, len(csP.digested), 1)
|
||||
assert.Check(t, cmp.Equal(csP.digested[0], desc.Digest))
|
||||
assert.Check(t, is.Equal(csP.digested[0], desc.Digest))
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/pkg/rootless"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
"github.com/docker/docker/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -117,15 +117,6 @@ func New(info logger.Info) (logger.Logger, error) {
|
||||
return nil, fmt.Errorf("No project was specified and couldn't read project from the metadata server. Please specify a project")
|
||||
}
|
||||
|
||||
// Issue #29344: gcplogs segfaults (static binary)
|
||||
// If HOME is not set, logging.NewClient() will call os/user.Current() via oauth2/google.
|
||||
// However, in static binary, os/user.Current() leads to segfault due to a glibc issue that won't be fixed
|
||||
// in a short term. (golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341)
|
||||
// So we forcibly set HOME so as to avoid call to os/user/Current()
|
||||
if err := ensureHomeIfIAmStatic(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := logging.NewClient(context.Background(), project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package gcplogs // import "github.com/docker/docker/daemon/logger/gcplogs"
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/dockerversion"
|
||||
"github.com/docker/docker/pkg/homedir"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ensureHomeIfIAmStatic ensure $HOME to be set if dockerversion.IAmStatic is "true".
|
||||
// See issue #29344: gcplogs segfaults (static binary)
|
||||
// If HOME is not set, logging.NewClient() will call os/user.Current() via oauth2/google.
|
||||
// If compiling statically, make sure osusergo build tag is also used to prevent a segfault
|
||||
// due to a glibc issue that won't be fixed in a short term
|
||||
// (see golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341).
|
||||
// So we forcibly set HOME so as to avoid call to os/user/Current()
|
||||
func ensureHomeIfIAmStatic() error {
|
||||
// Note: dockerversion.IAmStatic is only available for linux.
|
||||
// So we need to use them in this gcplogging_linux.go rather than in gcplogging.go
|
||||
if dockerversion.IAmStatic == "true" && os.Getenv("HOME") == "" {
|
||||
home := homedir.Get()
|
||||
logrus.Warnf("gcplogs requires HOME to be set for static daemon binary. Forcibly setting HOME to %s.", home)
|
||||
os.Setenv("HOME", home)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package gcplogs // import "github.com/docker/docker/daemon/logger/gcplogs"
|
||||
|
||||
func ensureHomeIfIAmStatic() error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"time"
|
||||
|
||||
"bytes"
|
||||
|
||||
"github.com/docker/docker/daemon/logger"
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/assert/cmp"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
type fakeLogger struct {
|
||||
@@ -75,7 +73,7 @@ func TestLog(t *testing.T) {
|
||||
case <-ctx.Done():
|
||||
t.Fatal("timed out waiting for messages... this is probably a test implementation error")
|
||||
case msg = <-cacher.messages:
|
||||
assert.Assert(t, cmp.DeepEqual(msg, m))
|
||||
assert.Assert(t, is.DeepEqual(msg, m))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/assert/cmp"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestSharedTempFileConverter(t *testing.T) {
|
||||
@@ -33,9 +33,9 @@ func TestSharedTempFileConverter(t *testing.T) {
|
||||
t.Logf("Iteration %v", i)
|
||||
|
||||
rdr := convertPath(t, uut, name)
|
||||
assert.Check(t, cmp.Equal("HELLO, WORLD!", readAll(t, rdr)))
|
||||
assert.Check(t, is.Equal("HELLO, WORLD!", readAll(t, rdr)))
|
||||
assert.Check(t, rdr.Close())
|
||||
assert.Check(t, cmp.Equal(fs.ErrClosed, rdr.Close()), "closing an already-closed reader should return an error")
|
||||
assert.Check(t, is.Equal(fs.ErrClosed, rdr.Close()), "closing an already-closed reader should return an error")
|
||||
}
|
||||
|
||||
assert.NilError(t, os.Remove(name))
|
||||
@@ -67,15 +67,15 @@ func TestSharedTempFileConverter(t *testing.T) {
|
||||
|
||||
rb1 := convertPath(t, uut, bpath) // Same path, different file.
|
||||
ra2 := convertPath(t, uut, apath) // New path, old file.
|
||||
assert.Check(t, cmp.Equal(2, conversions), "expected only one conversion per unique file")
|
||||
assert.Check(t, is.Equal(2, conversions), "expected only one conversion per unique file")
|
||||
|
||||
// Interleave reading and closing to shake out ref-counting bugs:
|
||||
// closing one reader shouldn't affect any other open readers.
|
||||
assert.Check(t, cmp.Equal("FILE A", readAll(t, ra1)))
|
||||
assert.Check(t, is.Equal("FILE A", readAll(t, ra1)))
|
||||
assert.NilError(t, ra1.Close())
|
||||
assert.Check(t, cmp.Equal("FILE A", readAll(t, ra2)))
|
||||
assert.Check(t, is.Equal("FILE A", readAll(t, ra2)))
|
||||
assert.NilError(t, ra2.Close())
|
||||
assert.Check(t, cmp.Equal("FILE B", readAll(t, rb1)))
|
||||
assert.Check(t, is.Equal("FILE B", readAll(t, rb1)))
|
||||
assert.NilError(t, rb1.Close())
|
||||
|
||||
assert.NilError(t, os.Remove(apath))
|
||||
@@ -120,7 +120,7 @@ func TestSharedTempFileConverter(t *testing.T) {
|
||||
t.Logf("goroutine %v: enter", i)
|
||||
defer t.Logf("goroutine %v: exit", i)
|
||||
f := convertPath(t, uut, name)
|
||||
assert.Check(t, cmp.Equal("HI THERE", readAll(t, f)), "in goroutine %v", i)
|
||||
assert.Check(t, is.Equal("HI THERE", readAll(t, f)), "in goroutine %v", i)
|
||||
closers <- f
|
||||
}()
|
||||
}
|
||||
@@ -138,12 +138,12 @@ func TestSharedTempFileConverter(t *testing.T) {
|
||||
f := convertPath(t, uut, name)
|
||||
closers <- f
|
||||
close(closers)
|
||||
assert.Check(t, cmp.Equal("HI THERE", readAll(t, f)), "after all goroutines returned")
|
||||
assert.Check(t, is.Equal("HI THERE", readAll(t, f)), "after all goroutines returned")
|
||||
for c := range closers {
|
||||
assert.Check(t, c.Close())
|
||||
}
|
||||
|
||||
assert.Check(t, cmp.Equal(int32(1), conversions))
|
||||
assert.Check(t, is.Equal(int32(1), conversions))
|
||||
|
||||
assert.NilError(t, os.Remove(name))
|
||||
checkDirEmpty(t, dir)
|
||||
@@ -197,7 +197,7 @@ func TestSharedTempFileConverter(t *testing.T) {
|
||||
fakeErr = nil
|
||||
f, err := uut.Do(src)
|
||||
assert.Check(t, err)
|
||||
assert.Check(t, cmp.Equal("HI THERE", readAll(t, f)))
|
||||
assert.Check(t, is.Equal("HI THERE", readAll(t, f)))
|
||||
assert.Check(t, f.Close())
|
||||
|
||||
// Files pending delete continue to show up in directory
|
||||
@@ -240,7 +240,7 @@ func checkDirEmpty(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
ls, err := os.ReadDir(path)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, cmp.Len(ls, 0), "directory should be free of temp files")
|
||||
assert.Check(t, is.Len(ls, 0), "directory should be free of temp files")
|
||||
}
|
||||
|
||||
func copyTransform(f func(string) string) func(dst io.WriteSeeker, src io.ReadSeeker) error {
|
||||
|
||||
@@ -108,7 +108,7 @@ func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error)
|
||||
return nil, libnetwork.ErrNoSuchNetwork(name)
|
||||
}
|
||||
if name == "" {
|
||||
name = c.Config().Daemon.DefaultNetwork
|
||||
name = c.Config().DefaultNetwork
|
||||
}
|
||||
return c.NetworkByName(name)
|
||||
}
|
||||
@@ -316,7 +316,7 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string
|
||||
c := daemon.netController
|
||||
driver := create.Driver
|
||||
if driver == "" {
|
||||
driver = c.Config().Daemon.DefaultDriver
|
||||
driver = c.Config().DefaultDriver
|
||||
}
|
||||
|
||||
nwOptions := []libnetwork.NetworkOption{
|
||||
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
"github.com/docker/docker/oci"
|
||||
"github.com/docker/docker/oci/caps"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/rootless/specconv"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/rootless/specconv"
|
||||
volumemounts "github.com/docker/docker/volume/mounts"
|
||||
"github.com/moby/sys/mount"
|
||||
"github.com/moby/sys/mountinfo"
|
||||
|
||||
@@ -53,8 +53,9 @@ func (daemon *Daemon) loadRuntimes() error {
|
||||
|
||||
func (daemon *Daemon) initRuntimes(runtimes map[string]types.Runtime) (err error) {
|
||||
runtimeDir := filepath.Join(daemon.configStore.Root, "runtimes")
|
||||
runtimeOldDir := runtimeDir + "-old"
|
||||
// Remove old temp directory if any
|
||||
os.RemoveAll(runtimeDir + "-old")
|
||||
os.RemoveAll(runtimeOldDir)
|
||||
tmpDir, err := os.MkdirTemp(daemon.configStore.Root, "gen-runtimes")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get temp dir to generate runtime scripts")
|
||||
@@ -68,15 +69,21 @@ func (daemon *Daemon) initRuntimes(runtimes map[string]types.Runtime) (err error
|
||||
return
|
||||
}
|
||||
|
||||
if err = os.Rename(runtimeDir, runtimeDir+"-old"); err != nil {
|
||||
return
|
||||
if err = os.Rename(runtimeDir, runtimeOldDir); err != nil {
|
||||
logrus.WithError(err).WithField("dir", runtimeDir).
|
||||
Warn("failed to rename runtimes dir to old. Will try to removing it")
|
||||
if err = os.RemoveAll(runtimeDir); err != nil {
|
||||
logrus.WithError(err).WithField("dir", runtimeDir).
|
||||
Warn("failed to remove old runtimes dir")
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = os.Rename(tmpDir, runtimeDir); err != nil {
|
||||
err = errors.Wrap(err, "failed to setup runtimes dir, new containers may not start")
|
||||
return
|
||||
}
|
||||
if err = os.RemoveAll(runtimeDir + "-old"); err != nil {
|
||||
logrus.WithError(err).WithField("dir", tmpDir).
|
||||
if err = os.RemoveAll(runtimeOldDir); err != nil {
|
||||
logrus.WithError(err).WithField("dir", runtimeOldDir).
|
||||
Warn("failed to remove old runtimes dir")
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -24,7 +24,10 @@ func TestGetRuntime(t *testing.T) {
|
||||
const configuredRtName = "my/custom.shim.v1"
|
||||
configuredRuntime := types.Runtime{Path: "/bin/true"}
|
||||
|
||||
d := &Daemon{configStore: config.New()}
|
||||
cfg, err := config.New()
|
||||
assert.NilError(t, err)
|
||||
|
||||
d := &Daemon{configStore: cfg}
|
||||
d.configStore.Root = t.TempDir()
|
||||
assert.Assert(t, os.Mkdir(filepath.Join(d.configStore.Root, "runtimes"), 0700))
|
||||
d.configStore.Runtimes = map[string]types.Runtime{
|
||||
|
||||
@@ -67,9 +67,9 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
|
||||
// if user has change the network mode on starting, clean up the
|
||||
// old networks. It is a deprecated feature and has been removed in Docker 1.12
|
||||
ctr.NetworkSettings.Networks = nil
|
||||
if err := ctr.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
return errdefs.System(err)
|
||||
}
|
||||
}
|
||||
if err := ctr.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
return errdefs.System(err)
|
||||
}
|
||||
ctr.InitDNSHostConfig()
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/libtrust"
|
||||
)
|
||||
|
||||
// LoadOrCreateTrustKey attempts to load the libtrust key at the given path,
|
||||
// otherwise generates a new one
|
||||
// TODO: this should use more of libtrust.LoadOrCreateTrustKey which may need
|
||||
// a refactor or this function to be moved into libtrust
|
||||
func loadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
|
||||
err := system.MkdirAll(filepath.Dir(trustKeyPath), 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trustKey, err := libtrust.LoadKeyFile(trustKeyPath)
|
||||
if err == libtrust.ErrKeyFileDoesNotExist {
|
||||
trustKey, err = libtrust.GenerateECP256PrivateKey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error generating key: %s", err)
|
||||
}
|
||||
encodedKey, err := serializePrivateKey(trustKey, filepath.Ext(trustKeyPath))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error serializing key: %s", err)
|
||||
}
|
||||
if err := ioutils.AtomicWriteFile(trustKeyPath, encodedKey, os.FileMode(0600)); err != nil {
|
||||
return nil, fmt.Errorf("Error saving key file: %s", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
return nil, fmt.Errorf("Error loading key file %s: %s", trustKeyPath, err)
|
||||
}
|
||||
return trustKey, nil
|
||||
}
|
||||
|
||||
func serializePrivateKey(key libtrust.PrivateKey, ext string) (encoded []byte, err error) {
|
||||
if ext == ".json" || ext == ".jwk" {
|
||||
encoded, err = json.Marshal(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to encode private key JWK: %s", err)
|
||||
}
|
||||
} else {
|
||||
pemBlock, err := key.PEMBlock()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to encode private key PEM: %s", err)
|
||||
}
|
||||
encoded = pem.EncodeToMemory(pemBlock)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/fs"
|
||||
)
|
||||
|
||||
// LoadOrCreateTrustKey
|
||||
func TestLoadOrCreateTrustKeyInvalidKeyFile(t *testing.T) {
|
||||
tmpKeyFolderPath, err := os.MkdirTemp("", "api-trustkey-test")
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(tmpKeyFolderPath)
|
||||
|
||||
tmpKeyFile, err := os.CreateTemp(tmpKeyFolderPath, "keyfile")
|
||||
assert.NilError(t, err)
|
||||
defer tmpKeyFile.Close()
|
||||
|
||||
_, err = loadOrCreateTrustKey(tmpKeyFile.Name())
|
||||
assert.Check(t, is.ErrorContains(err, "Error loading key file"))
|
||||
}
|
||||
|
||||
func TestLoadOrCreateTrustKeyCreateKeyWhenFileDoesNotExist(t *testing.T) {
|
||||
tmpKeyFolderPath := fs.NewDir(t, "api-trustkey-test")
|
||||
defer tmpKeyFolderPath.Remove()
|
||||
|
||||
// Without the need to create the folder hierarchy
|
||||
tmpKeyFile := tmpKeyFolderPath.Join("keyfile")
|
||||
|
||||
key, err := loadOrCreateTrustKey(tmpKeyFile)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, key != nil)
|
||||
|
||||
_, err = os.Stat(tmpKeyFile)
|
||||
assert.NilError(t, err, "key file doesn't exist")
|
||||
}
|
||||
|
||||
func TestLoadOrCreateTrustKeyCreateKeyWhenDirectoryDoesNotExist(t *testing.T) {
|
||||
tmpKeyFolderPath := fs.NewDir(t, "api-trustkey-test")
|
||||
defer tmpKeyFolderPath.Remove()
|
||||
tmpKeyFile := tmpKeyFolderPath.Join("folder/hierarchy/keyfile")
|
||||
|
||||
key, err := loadOrCreateTrustKey(tmpKeyFile)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, key != nil)
|
||||
|
||||
_, err = os.Stat(tmpKeyFile)
|
||||
assert.NilError(t, err, "key file doesn't exist")
|
||||
}
|
||||
|
||||
func TestLoadOrCreateTrustKeyCreateKeyNoPath(t *testing.T) {
|
||||
defer os.Remove("keyfile")
|
||||
key, err := loadOrCreateTrustKey("keyfile")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, key != nil)
|
||||
|
||||
_, err = os.Stat("keyfile")
|
||||
assert.NilError(t, err, "key file doesn't exist")
|
||||
}
|
||||
|
||||
func TestLoadOrCreateTrustKeyLoadValidKey(t *testing.T) {
|
||||
tmpKeyFile := filepath.Join("testdata", "keyfile")
|
||||
key, err := loadOrCreateTrustKey(tmpKeyFile)
|
||||
assert.NilError(t, err)
|
||||
expected := "AWX2:I27X:WQFX:IOMK:CNAK:O7PW:VYNB:ZLKC:CVAE:YJP2:SI4A:XXAY"
|
||||
assert.Check(t, is.Contains(key.String(), expected))
|
||||
}
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/docker/docker/pkg/system"
|
||||
refstore "github.com/docker/docker/reference"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/libtrust"
|
||||
"github.com/opencontainers/go-digest"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
@@ -47,8 +46,6 @@ type Config struct {
|
||||
// ReferenceStore manages tags. This value is optional, when excluded
|
||||
// content will not be tagged.
|
||||
ReferenceStore refstore.Store
|
||||
// RequireSchema2 ensures that only schema2 manifests are used.
|
||||
RequireSchema2 bool
|
||||
}
|
||||
|
||||
// ImagePullConfig stores pull configuration.
|
||||
@@ -74,9 +71,6 @@ type ImagePushConfig struct {
|
||||
ConfigMediaType string
|
||||
// LayerStores manages layers.
|
||||
LayerStores PushLayerProvider
|
||||
// TrustKey is the private key for legacy signatures. This is typically
|
||||
// an ephemeral key, since these signatures are no longer verified.
|
||||
TrustKey libtrust.PrivateKey
|
||||
// UploadManager dispatches uploads.
|
||||
UploadManager *xfer.LayerUploadManager
|
||||
}
|
||||
|
||||
@@ -117,11 +117,11 @@ func (serv *v2MetadataService) digestNamespace() string {
|
||||
}
|
||||
|
||||
func (serv *v2MetadataService) diffIDKey(diffID layer.DiffID) string {
|
||||
return string(digest.Digest(diffID).Algorithm()) + "/" + digest.Digest(diffID).Hex()
|
||||
return string(digest.Digest(diffID).Algorithm()) + "/" + digest.Digest(diffID).Encoded()
|
||||
}
|
||||
|
||||
func (serv *v2MetadataService) digestKey(dgst digest.Digest) string {
|
||||
return string(dgst.Algorithm()) + "/" + dgst.Hex()
|
||||
return string(dgst.Algorithm()) + "/" + dgst.Encoded()
|
||||
}
|
||||
|
||||
// GetMetadata finds the metadata associated with a layer DiffID.
|
||||
|
||||
@@ -438,10 +438,6 @@ func (p *puller) pullTag(ctx context.Context, ref reference.Named, platform *spe
|
||||
|
||||
switch v := manifest.(type) {
|
||||
case *schema1.SignedManifest:
|
||||
if p.config.RequireSchema2 {
|
||||
return false, fmt.Errorf("invalid manifest: not schema2")
|
||||
}
|
||||
|
||||
// give registries time to upgrade to schema2 and only warn if we know a registry has been upgraded long time ago
|
||||
// TODO: condition to be removed
|
||||
if reference.Domain(ref) == "docker.io" {
|
||||
@@ -608,14 +604,12 @@ func (p *puller) pullSchema1(ctx context.Context, ref reference.Reference, unver
|
||||
}
|
||||
|
||||
func checkSupportedMediaType(mediaType string) error {
|
||||
supportedMediaTypes := []string{
|
||||
"application/vnd.oci.image.",
|
||||
"application/vnd.docker.",
|
||||
}
|
||||
|
||||
lowerMt := strings.ToLower(mediaType)
|
||||
for _, mt := range supportedMediaTypes {
|
||||
if strings.HasPrefix(lowerMt, mt) {
|
||||
// The should either be an exact match, or have a valid prefix
|
||||
// we append a "." when matching prefixes to exclude "false positives";
|
||||
// for example, we don't want to match "application/vnd.oci.images_are_fun_yolo".
|
||||
if lowerMt == mt || strings.HasPrefix(lowerMt, mt+".") {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/docker/docker/pkg/progress"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/libtrust"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -187,7 +188,7 @@ func (p *pusher) pushTag(ctx context.Context, ref reference.NamedTagged, id dige
|
||||
|
||||
putOptions := []distribution.ManifestServiceOption{distribution.WithTag(ref.Tag())}
|
||||
if _, err = manSvc.Put(ctx, manifest, putOptions...); err != nil {
|
||||
if runtime.GOOS == "windows" || p.config.TrustKey == nil || p.config.RequireSchema2 {
|
||||
if runtime.GOOS == "windows" {
|
||||
logrus.Warnf("failed to upload schema2 manifest: %v", err)
|
||||
return err
|
||||
}
|
||||
@@ -211,7 +212,11 @@ func (p *pusher) pushTag(ctx context.Context, ref reference.NamedTagged, id dige
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
builder = schema1.NewConfigManifestBuilder(p.repo.Blobs(ctx), p.config.TrustKey, manifestRef, imgConfig)
|
||||
pk, err := libtrust.GenerateECP256PrivateKey()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unexpected error generating private key")
|
||||
}
|
||||
builder = schema1.NewConfigManifestBuilder(p.repo.Blobs(ctx), pk, manifestRef, imgConfig)
|
||||
manifest, err = manifestFromBuilder(ctx, builder, descriptors)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -20,6 +20,22 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// supportedMediaTypes represents acceptable media-type(-prefixes)
|
||||
// we use this list to prevent obscure errors when trying to pull
|
||||
// OCI artifacts.
|
||||
supportedMediaTypes = []string{
|
||||
// valid prefixes
|
||||
"application/vnd.oci.image",
|
||||
"application/vnd.docker",
|
||||
|
||||
// these types may occur on old images, and are copied from
|
||||
// defaultImageTypes below.
|
||||
"application/octet-stream",
|
||||
"application/json",
|
||||
"text/html",
|
||||
"",
|
||||
}
|
||||
|
||||
// defaultImageTypes represents the schema2 config types for images
|
||||
defaultImageTypes = []string{
|
||||
schema2.MediaTypeImageConfig,
|
||||
|
||||
149
docker-bake.hcl
149
docker-bake.hcl
@@ -1,14 +1,87 @@
|
||||
variable "BUNDLES_OUTPUT" {
|
||||
default = "./bundles"
|
||||
variable "APT_MIRROR" {
|
||||
default = "cdn-fastly.deb.debian.org"
|
||||
}
|
||||
variable "DOCKER_CROSSPLATFORMS" {
|
||||
variable "DOCKER_DEBUG" {
|
||||
default = ""
|
||||
}
|
||||
variable "DOCKER_STATIC" {
|
||||
default = "1"
|
||||
}
|
||||
variable "DOCKER_LDFLAGS" {
|
||||
default = ""
|
||||
}
|
||||
variable "DOCKER_BUILDTAGS" {
|
||||
default = ""
|
||||
}
|
||||
variable "DOCKER_GITCOMMIT" {
|
||||
default = "HEAD"
|
||||
}
|
||||
|
||||
# Docker version such as 23.0.0-dev. Automatically generated through Git ref.
|
||||
variable "VERSION" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# The platform name, such as "Docker Engine - Community".
|
||||
variable "PLATFORM" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# The product name, used to set version.ProductName, which is used to set
|
||||
# BuildKit's ExportedProduct variable in order to show useful error messages
|
||||
# to users when a certain version of the product doesn't support a BuildKit feature.
|
||||
variable "PRODUCT" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Sets the version.DefaultProductLicense string, such as "Community Engine".
|
||||
# This field can contain a summary of the product license of the daemon if a
|
||||
# commercial license has been applied to the daemon.
|
||||
variable "DEFAULT_PRODUCT_LICENSE" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# The name of the packager (e.g. "Docker, Inc."). This used to set CompanyName
|
||||
# in the manifest.
|
||||
variable "PACKAGER_NAME" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# GITHUB_REF is the actual ref that triggers the workflow and used as version
|
||||
# when tag is pushed: https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables
|
||||
variable "GITHUB_REF" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# GITHUB_SHA is the commit SHA that triggered the workflow and used as commit.
|
||||
# https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables
|
||||
variable "GITHUB_SHA" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Defines the output folder
|
||||
variable "DESTDIR" {
|
||||
default = ""
|
||||
}
|
||||
function "bindir" {
|
||||
params = [defaultdir]
|
||||
result = DESTDIR != "" ? DESTDIR : "./bundles/${defaultdir}"
|
||||
}
|
||||
|
||||
target "_common" {
|
||||
args = {
|
||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1
|
||||
APT_MIRROR = "cdn-fastly.deb.debian.org"
|
||||
APT_MIRROR = APT_MIRROR
|
||||
DOCKER_DEBUG = DOCKER_DEBUG
|
||||
DOCKER_STATIC = DOCKER_STATIC
|
||||
DOCKER_LDFLAGS = DOCKER_LDFLAGS
|
||||
DOCKER_BUILDTAGS = DOCKER_BUILDTAGS
|
||||
DOCKER_GITCOMMIT = DOCKER_GITCOMMIT != "" ? DOCKER_GITCOMMIT : GITHUB_SHA
|
||||
VERSION = VERSION != "" ? VERSION : GITHUB_REF
|
||||
PLATFORM = PLATFORM
|
||||
PRODUCT = PRODUCT
|
||||
DEFAULT_PRODUCT_LICENSE = DEFAULT_PRODUCT_LICENSE
|
||||
PACKAGER_NAME = PACKAGER_NAME
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,43 +89,83 @@ group "default" {
|
||||
targets = ["binary"]
|
||||
}
|
||||
|
||||
target "_platforms" {
|
||||
platforms = [
|
||||
"linux/amd64",
|
||||
"linux/arm/v5",
|
||||
"linux/arm/v6",
|
||||
"linux/arm/v7",
|
||||
"linux/arm64",
|
||||
"linux/ppc64le",
|
||||
"linux/s390x",
|
||||
"windows/amd64"
|
||||
]
|
||||
}
|
||||
|
||||
#
|
||||
# build dockerd and docker-proxy
|
||||
#
|
||||
|
||||
target "binary" {
|
||||
inherits = ["_common"]
|
||||
target = "binary"
|
||||
output = [BUNDLES_OUTPUT]
|
||||
output = [bindir(DOCKER_STATIC == "1" ? "binary" : "dynbinary")]
|
||||
}
|
||||
|
||||
target "dynbinary" {
|
||||
inherits = ["binary"]
|
||||
target = "dynbinary"
|
||||
output = [bindir("dynbinary")]
|
||||
args = {
|
||||
DOCKER_STATIC = "0"
|
||||
}
|
||||
}
|
||||
|
||||
target "cross" {
|
||||
inherits = ["binary"]
|
||||
args = {
|
||||
CROSS = "true"
|
||||
DOCKER_CROSSPLATFORMS = DOCKER_CROSSPLATFORMS
|
||||
}
|
||||
target = "cross"
|
||||
target "binary-cross" {
|
||||
inherits = ["binary", "_platforms"]
|
||||
}
|
||||
|
||||
target "binary-smoketest" {
|
||||
inherits = ["_common"]
|
||||
target = "smoketest"
|
||||
output = ["type=cacheonly"]
|
||||
platforms = [
|
||||
"linux/amd64",
|
||||
"linux/arm/v6",
|
||||
"linux/arm/v7",
|
||||
"linux/arm64",
|
||||
"linux/ppc64le",
|
||||
"linux/s390x"
|
||||
]
|
||||
}
|
||||
|
||||
#
|
||||
# same as binary but with extra tools as well (containerd, runc, ...)
|
||||
#
|
||||
|
||||
target "all" {
|
||||
inherits = ["_common"]
|
||||
target = "all"
|
||||
output = [bindir(DOCKER_STATIC == "1" ? "binary" : "dynbinary")]
|
||||
}
|
||||
|
||||
target "all-cross" {
|
||||
inherits = ["all", "_platforms"]
|
||||
}
|
||||
|
||||
#
|
||||
# dev
|
||||
#
|
||||
|
||||
variable "DEV_IMAGE" {
|
||||
default = "docker-dev"
|
||||
}
|
||||
variable "SYSTEMD" {
|
||||
default = "false"
|
||||
}
|
||||
|
||||
target "dev" {
|
||||
inherits = ["_common"]
|
||||
target = "final"
|
||||
target = "dev"
|
||||
args = {
|
||||
SYSTEMD = SYSTEMD
|
||||
}
|
||||
tags = [DEV_IMAGE]
|
||||
tags = ["docker-dev"]
|
||||
output = ["type=docker"]
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ var (
|
||||
GitCommit = "library-import"
|
||||
Version = "library-import"
|
||||
BuildTime = "library-import"
|
||||
IAmStatic = "library-import"
|
||||
PlatformName = ""
|
||||
ProductName = ""
|
||||
DefaultProductLicense = ""
|
||||
|
||||
@@ -573,6 +573,7 @@ definitions:
|
||||
to not change.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
x-nullable: true
|
||||
Ulimits:
|
||||
description: |
|
||||
A list of resource limits to set in the container. For example:
|
||||
@@ -694,11 +695,13 @@ definitions:
|
||||
The time to wait between checks in nanoseconds. It should be 0 or at
|
||||
least 1000000 (1 ms). 0 means inherit.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
Timeout:
|
||||
description: |
|
||||
The time to wait before considering the check to have hung. It should
|
||||
be 0 or at least 1000000 (1 ms). 0 means inherit.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
Retries:
|
||||
description: |
|
||||
The number of consecutive failures needed to consider a container as
|
||||
@@ -710,11 +713,13 @@ definitions:
|
||||
health-retries countdown in nanoseconds. It should be 0 or at least
|
||||
1000000 (1 ms). 0 means inherit.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
|
||||
Health:
|
||||
description: |
|
||||
Health stores information about the container's healthcheck results.
|
||||
type: "object"
|
||||
x-nullable: true
|
||||
properties:
|
||||
Status:
|
||||
description: |
|
||||
@@ -740,13 +745,13 @@ definitions:
|
||||
description: |
|
||||
Log contains the last few results (oldest first)
|
||||
items:
|
||||
x-nullable: true
|
||||
$ref: "#/definitions/HealthcheckResult"
|
||||
|
||||
HealthcheckResult:
|
||||
description: |
|
||||
HealthcheckResult stores information about a single run of a healthcheck probe
|
||||
type: "object"
|
||||
x-nullable: true
|
||||
properties:
|
||||
Start:
|
||||
description: |
|
||||
@@ -1014,6 +1019,7 @@ definitions:
|
||||
remapping option is enabled.
|
||||
ShmSize:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
description: |
|
||||
Size of `/dev/shm` in bytes. If omitted, the system uses 64MB.
|
||||
minimum: 0
|
||||
@@ -1534,7 +1540,7 @@ definitions:
|
||||
List of image names/tags in the local image cache that reference this
|
||||
image.
|
||||
|
||||
Multiple image tags can refer to the same imagem and this list may be
|
||||
Multiple image tags can refer to the same image, and this list may be
|
||||
empty if no tags reference the image, in which case the image is
|
||||
"untagged", in which case it can still be referenced by its ID.
|
||||
type: "array"
|
||||
@@ -1735,7 +1741,7 @@ definitions:
|
||||
List of image names/tags in the local image cache that reference this
|
||||
image.
|
||||
|
||||
Multiple image tags can refer to the same imagem and this list may be
|
||||
Multiple image tags can refer to the same image, and this list may be
|
||||
empty if no tags reference the image, in which case the image is
|
||||
"untagged", in which case it can still be referenced by its ID.
|
||||
type: "array"
|
||||
@@ -1785,6 +1791,7 @@ definitions:
|
||||
This size is not calculated by default. `-1` indicates that the value
|
||||
has not been set / calculated.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
x-nullable: false
|
||||
example: 1239828
|
||||
VirtualSize:
|
||||
@@ -1929,6 +1936,7 @@ definitions:
|
||||
properties:
|
||||
Size:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
default: -1
|
||||
description: |
|
||||
Amount of disk space used by the volume (in bytes). This information
|
||||
@@ -1938,6 +1946,7 @@ definitions:
|
||||
x-nullable: false
|
||||
RefCount:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
default: -1
|
||||
description: |
|
||||
The number of containers referencing this volume. This field
|
||||
@@ -2213,6 +2222,8 @@ definitions:
|
||||
type: "string"
|
||||
error:
|
||||
type: "string"
|
||||
errorDetail:
|
||||
$ref: "#/definitions/ErrorDetail"
|
||||
status:
|
||||
type: "string"
|
||||
progress:
|
||||
@@ -4301,6 +4312,7 @@ definitions:
|
||||
ContainerState stores container's running state. It's part of ContainerJSONBase
|
||||
and will be returned by the "inspect" command.
|
||||
type: "object"
|
||||
x-nullable: true
|
||||
properties:
|
||||
Status:
|
||||
description: |
|
||||
@@ -4358,7 +4370,6 @@ definitions:
|
||||
type: "string"
|
||||
example: "2020-01-06T09:07:59.461876391Z"
|
||||
Health:
|
||||
x-nullable: true
|
||||
$ref: "#/definitions/Health"
|
||||
|
||||
ContainerWaitResponse:
|
||||
@@ -4371,6 +4382,7 @@ definitions:
|
||||
StatusCode:
|
||||
description: "Exit code of the container"
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
x-nullable: false
|
||||
Error:
|
||||
$ref: "#/definitions/ContainerWaitExitError"
|
||||
@@ -4480,7 +4492,6 @@ definitions:
|
||||
type: "string"
|
||||
example: "2020-06-22T15:49:27.000000000+00:00"
|
||||
|
||||
|
||||
SystemInfo:
|
||||
type: "object"
|
||||
properties:
|
||||
@@ -5724,7 +5735,6 @@ paths:
|
||||
items:
|
||||
type: "string"
|
||||
State:
|
||||
x-nullable: true
|
||||
$ref: "#/definitions/ContainerState"
|
||||
Image:
|
||||
description: "The container's image ID"
|
||||
@@ -5737,9 +5747,6 @@ paths:
|
||||
type: "string"
|
||||
LogPath:
|
||||
type: "string"
|
||||
Node:
|
||||
description: "TODO"
|
||||
type: "object"
|
||||
Name:
|
||||
type: "string"
|
||||
RestartCount:
|
||||
@@ -6519,7 +6526,8 @@ paths:
|
||||
type: "string"
|
||||
- name: "signal"
|
||||
in: "query"
|
||||
description: "Signal to send to the container as an integer or string (e.g. `SIGINT`)"
|
||||
description: |
|
||||
Signal to send to the container as an integer or string (e.g. `SIGINT`).
|
||||
type: "string"
|
||||
default: "SIGKILL"
|
||||
tags: ["Container"]
|
||||
@@ -7897,6 +7905,10 @@ paths:
|
||||
IdentityToken: "9cbaf023786cd7..."
|
||||
204:
|
||||
description: "No error"
|
||||
401:
|
||||
description: "Auth error"
|
||||
schema:
|
||||
$ref: "#/definitions/ErrorResponse"
|
||||
500:
|
||||
description: "Server error"
|
||||
schema:
|
||||
@@ -8732,6 +8744,7 @@ paths:
|
||||
type: "boolean"
|
||||
default: false
|
||||
tags: ["Volume"]
|
||||
|
||||
/volumes/prune:
|
||||
post:
|
||||
summary: "Delete unused volumes"
|
||||
|
||||
@@ -746,11 +746,13 @@ definitions:
|
||||
The time to wait between checks in nanoseconds. It should be 0 or at
|
||||
least 1000000 (1 ms). 0 means inherit.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
Timeout:
|
||||
description: |
|
||||
The time to wait before considering the check to have hung. It should
|
||||
be 0 or at least 1000000 (1 ms). 0 means inherit.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
Retries:
|
||||
description: |
|
||||
The number of consecutive failures needed to consider a container as
|
||||
@@ -762,11 +764,13 @@ definitions:
|
||||
health-retries countdown in nanoseconds. It should be 0 or at least
|
||||
1000000 (1 ms). 0 means inherit.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
|
||||
Health:
|
||||
description: |
|
||||
Health stores information about the container's healthcheck results.
|
||||
type: "object"
|
||||
x-nullable: true
|
||||
properties:
|
||||
Status:
|
||||
description: |
|
||||
@@ -792,13 +796,13 @@ definitions:
|
||||
description: |
|
||||
Log contains the last few results (oldest first)
|
||||
items:
|
||||
x-nullable: true
|
||||
$ref: "#/definitions/HealthcheckResult"
|
||||
|
||||
HealthcheckResult:
|
||||
description: |
|
||||
HealthcheckResult stores information about a single run of a healthcheck probe
|
||||
type: "object"
|
||||
x-nullable: true
|
||||
properties:
|
||||
Start:
|
||||
description: |
|
||||
@@ -1075,6 +1079,7 @@ definitions:
|
||||
remapping option is enabled.
|
||||
ShmSize:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
description: |
|
||||
Size of `/dev/shm` in bytes. If omitted, the system uses 64MB.
|
||||
minimum: 0
|
||||
@@ -1595,7 +1600,7 @@ definitions:
|
||||
List of image names/tags in the local image cache that reference this
|
||||
image.
|
||||
|
||||
Multiple image tags can refer to the same imagem and this list may be
|
||||
Multiple image tags can refer to the same image, and this list may be
|
||||
empty if no tags reference the image, in which case the image is
|
||||
"untagged", in which case it can still be referenced by its ID.
|
||||
type: "array"
|
||||
@@ -1796,7 +1801,7 @@ definitions:
|
||||
List of image names/tags in the local image cache that reference this
|
||||
image.
|
||||
|
||||
Multiple image tags can refer to the same imagem and this list may be
|
||||
Multiple image tags can refer to the same image, and this list may be
|
||||
empty if no tags reference the image, in which case the image is
|
||||
"untagged", in which case it can still be referenced by its ID.
|
||||
type: "array"
|
||||
@@ -1846,6 +1851,7 @@ definitions:
|
||||
This size is not calculated by default. `-1` indicates that the value
|
||||
has not been set / calculated.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
x-nullable: false
|
||||
example: 1239828
|
||||
VirtualSize:
|
||||
@@ -1990,6 +1996,7 @@ definitions:
|
||||
properties:
|
||||
Size:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
default: -1
|
||||
description: |
|
||||
Amount of disk space used by the volume (in bytes). This information
|
||||
@@ -1999,6 +2006,7 @@ definitions:
|
||||
x-nullable: false
|
||||
RefCount:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
default: -1
|
||||
description: |
|
||||
The number of containers referencing this volume. This field
|
||||
@@ -2274,6 +2282,8 @@ definitions:
|
||||
type: "string"
|
||||
error:
|
||||
type: "string"
|
||||
errorDetail:
|
||||
$ref: "#/definitions/ErrorDetail"
|
||||
status:
|
||||
type: "string"
|
||||
progress:
|
||||
@@ -4426,6 +4436,7 @@ definitions:
|
||||
ContainerState stores container's running state. It's part of ContainerJSONBase
|
||||
and will be returned by the "inspect" command.
|
||||
type: "object"
|
||||
x-nullable: true
|
||||
properties:
|
||||
Status:
|
||||
description: |
|
||||
@@ -4483,7 +4494,6 @@ definitions:
|
||||
type: "string"
|
||||
example: "2020-01-06T09:07:59.461876391Z"
|
||||
Health:
|
||||
x-nullable: true
|
||||
$ref: "#/definitions/Health"
|
||||
|
||||
ContainerWaitResponse:
|
||||
@@ -4496,6 +4506,7 @@ definitions:
|
||||
StatusCode:
|
||||
description: "Exit code of the container"
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
x-nullable: false
|
||||
Error:
|
||||
$ref: "#/definitions/ContainerWaitExitError"
|
||||
@@ -6023,7 +6034,6 @@ paths:
|
||||
items:
|
||||
type: "string"
|
||||
State:
|
||||
x-nullable: true
|
||||
$ref: "#/definitions/ContainerState"
|
||||
Image:
|
||||
description: "The container's image ID"
|
||||
@@ -6036,9 +6046,6 @@ paths:
|
||||
type: "string"
|
||||
LogPath:
|
||||
type: "string"
|
||||
Node:
|
||||
description: "TODO"
|
||||
type: "object"
|
||||
Name:
|
||||
type: "string"
|
||||
RestartCount:
|
||||
@@ -6825,7 +6832,8 @@ paths:
|
||||
type: "string"
|
||||
- name: "signal"
|
||||
in: "query"
|
||||
description: "Signal to send to the container as an integer or string (e.g. `SIGINT`)"
|
||||
description: |
|
||||
Signal to send to the container as an integer or string (e.g. `SIGINT`).
|
||||
type: "string"
|
||||
default: "SIGKILL"
|
||||
tags: ["Container"]
|
||||
@@ -8220,6 +8228,10 @@ paths:
|
||||
IdentityToken: "9cbaf023786cd7..."
|
||||
204:
|
||||
description: "No error"
|
||||
401:
|
||||
description: "Auth error"
|
||||
schema:
|
||||
$ref: "#/definitions/ErrorResponse"
|
||||
500:
|
||||
description: "Server error"
|
||||
schema:
|
||||
@@ -9065,6 +9077,7 @@ paths:
|
||||
type: "boolean"
|
||||
default: false
|
||||
tags: ["Volume"]
|
||||
|
||||
/volumes/prune:
|
||||
post:
|
||||
summary: "Delete unused volumes"
|
||||
@@ -10083,7 +10096,7 @@ paths:
|
||||
required: true
|
||||
schema:
|
||||
type: "object"
|
||||
title: "SwarmJoinRequest"
|
||||
title: "SwarmInitRequest"
|
||||
properties:
|
||||
ListenAddr:
|
||||
description: |
|
||||
@@ -10182,7 +10195,7 @@ paths:
|
||||
required: true
|
||||
schema:
|
||||
type: "object"
|
||||
title: "SwarmInitRequest"
|
||||
title: "SwarmJoinRequest"
|
||||
properties:
|
||||
ListenAddr:
|
||||
description: |
|
||||
|
||||
@@ -823,13 +823,13 @@ definitions:
|
||||
description: |
|
||||
Log contains the last few results (oldest first)
|
||||
items:
|
||||
x-nullable: true
|
||||
$ref: "#/definitions/HealthcheckResult"
|
||||
|
||||
HealthcheckResult:
|
||||
description: |
|
||||
HealthcheckResult stores information about a single run of a healthcheck probe
|
||||
type: "object"
|
||||
x-nullable: true
|
||||
properties:
|
||||
Start:
|
||||
description: |
|
||||
@@ -2325,6 +2325,8 @@ definitions:
|
||||
type: "string"
|
||||
error:
|
||||
type: "string"
|
||||
errorDetail:
|
||||
$ref: "#/definitions/ErrorDetail"
|
||||
status:
|
||||
type: "string"
|
||||
progress:
|
||||
@@ -4599,6 +4601,7 @@ definitions:
|
||||
ContainerState stores container's running state. It's part of ContainerJSONBase
|
||||
and will be returned by the "inspect" command.
|
||||
type: "object"
|
||||
x-nullable: true
|
||||
properties:
|
||||
Status:
|
||||
description: |
|
||||
@@ -4656,7 +4659,6 @@ definitions:
|
||||
type: "string"
|
||||
example: "2020-01-06T09:07:59.461876391Z"
|
||||
Health:
|
||||
x-nullable: true
|
||||
$ref: "#/definitions/Health"
|
||||
|
||||
ContainerWaitResponse:
|
||||
@@ -6224,7 +6226,6 @@ paths:
|
||||
items:
|
||||
type: "string"
|
||||
State:
|
||||
x-nullable: true
|
||||
$ref: "#/definitions/ContainerState"
|
||||
Image:
|
||||
description: "The container's image ID"
|
||||
@@ -7036,7 +7037,8 @@ paths:
|
||||
type: "string"
|
||||
- name: "signal"
|
||||
in: "query"
|
||||
description: "Signal to send to the container as an integer or string (e.g. `SIGINT`)"
|
||||
description: |
|
||||
Signal to send to the container as an integer or string (e.g. `SIGINT`).
|
||||
type: "string"
|
||||
default: "SIGKILL"
|
||||
tags: ["Container"]
|
||||
@@ -8431,6 +8433,10 @@ paths:
|
||||
IdentityToken: "9cbaf023786cd7..."
|
||||
204:
|
||||
description: "No error"
|
||||
401:
|
||||
description: "Auth error"
|
||||
schema:
|
||||
$ref: "#/definitions/ErrorResponse"
|
||||
500:
|
||||
description: "Server error"
|
||||
schema:
|
||||
@@ -9278,6 +9284,7 @@ paths:
|
||||
type: "boolean"
|
||||
default: false
|
||||
tags: ["Volume"]
|
||||
|
||||
/volumes/prune:
|
||||
post:
|
||||
summary: "Delete unused volumes"
|
||||
|
||||
@@ -1122,6 +1122,7 @@ definitions:
|
||||
remapping option is enabled.
|
||||
ShmSize:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
description: |
|
||||
Size of `/dev/shm` in bytes. If omitted, the system uses 64MB.
|
||||
minimum: 0
|
||||
@@ -2343,6 +2344,8 @@ definitions:
|
||||
type: "string"
|
||||
error:
|
||||
type: "string"
|
||||
errorDetail:
|
||||
$ref: "#/definitions/ErrorDetail"
|
||||
status:
|
||||
type: "string"
|
||||
progress:
|
||||
@@ -8725,6 +8728,10 @@ paths:
|
||||
IdentityToken: "9cbaf023786cd7..."
|
||||
204:
|
||||
description: "No error"
|
||||
401:
|
||||
description: "Auth error"
|
||||
schema:
|
||||
$ref: "#/definitions/ErrorResponse"
|
||||
500:
|
||||
description: "Server error"
|
||||
schema:
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
* (Optional) [Configure project for IDE](set-up-ide.md)
|
||||
* [Configure Git for contributing](set-up-git.md)
|
||||
* [Work with a development container](set-up-dev-env.md)
|
||||
* [Containerized build and cross compilation](ctn-build.md)
|
||||
* [Run tests and test documentation](test.md)
|
||||
* [Debugging the daemon](debug.md)
|
||||
|
||||
28
docs/contributing/ctn-build.md
Normal file
28
docs/contributing/ctn-build.md
Normal file
@@ -0,0 +1,28 @@
|
||||
The `Dockerfile` supports building and cross compiling docker daemon and extra
|
||||
tools using [Docker Buildx](https://github.com/docker/buildx) and [BuildKit](https://github.com/moby/buildkit).
|
||||
A [bake definition](https://docs.docker.com/build/bake/file-definition/) named
|
||||
`docker-bake.hcl` is in place to ease the build process:
|
||||
|
||||
```shell
|
||||
# build binaries for the current host platform
|
||||
# output to ./bundles/binary-daemon by default
|
||||
docker buildx bake
|
||||
# or
|
||||
docker buildx bake binary
|
||||
|
||||
# build binaries for the current host platform
|
||||
# output to ./bin
|
||||
DESTDIR=./bin docker buildx bake
|
||||
|
||||
# build dynamically linked binaries
|
||||
# output to ./bundles/dynbinary-daemon by default
|
||||
DOCKER_STATIC=0 docker buildx bake
|
||||
# or
|
||||
docker buildx bake dynbinary
|
||||
|
||||
# build binaries for all supported platforms
|
||||
docker buildx bake binary-cross
|
||||
|
||||
# build binaries for a specific platform
|
||||
docker buildx bake --set *.platform=linux/arm64
|
||||
```
|
||||
@@ -150,10 +150,10 @@ can take over 15 minutes to complete.
|
||||
Removing bundles/
|
||||
|
||||
---> Making bundle: binary (in bundles/binary)
|
||||
Building: bundles/binary-daemon/dockerd-17.06.0-dev
|
||||
Created binary: bundles/binary-daemon/dockerd-17.06.0-dev
|
||||
Copying nested executables into bundles/binary-daemon
|
||||
|
||||
Building bundles/binary-daemon/dockerd (linux/amd64)...
|
||||
Created binary: bundles/binary-daemon/dockerd
|
||||
Building bundles/binary-daemon/docker-proxy (linux/amd64)...
|
||||
Created binary:bundles/binary-daemon/docker-proxy
|
||||
```
|
||||
|
||||
7. Run `make install`, which copies the binary to the container's
|
||||
|
||||
@@ -123,7 +123,7 @@ Try this now.
|
||||
4. Run the tests using the `hack/make.sh` script.
|
||||
|
||||
```bash
|
||||
# hack/make.sh dynbinary binary cross test-integration test-docker-py
|
||||
# hack/make.sh dynbinary binary test-integration test-docker-py
|
||||
```
|
||||
|
||||
The tests run just as they did within your local host.
|
||||
@@ -132,11 +132,11 @@ Try this now.
|
||||
just the integration tests:
|
||||
|
||||
```bash
|
||||
# hack/make.sh dynbinary binary cross test-integration
|
||||
# hack/make.sh dynbinary binary test-integration
|
||||
```
|
||||
|
||||
Most test targets require that you build these precursor targets first:
|
||||
`dynbinary binary cross`
|
||||
`dynbinary binary`
|
||||
|
||||
|
||||
## Run unit tests
|
||||
|
||||
@@ -2,14 +2,12 @@ package errdefs // import "github.com/docker/docker/errdefs"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// FromStatusCode creates an errdef error, based on the provided HTTP status-code
|
||||
func FromStatusCode(err error, statusCode int) error {
|
||||
if err == nil {
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
switch statusCode {
|
||||
case http.StatusNotFound:
|
||||
@@ -33,11 +31,6 @@ func FromStatusCode(err error, statusCode int) error {
|
||||
err = System(err)
|
||||
}
|
||||
default:
|
||||
logrus.WithError(err).WithFields(logrus.Fields{
|
||||
"module": "api",
|
||||
"status_code": statusCode,
|
||||
}).Debug("FIXME: Got an status-code for which error does not match any expected type!!!")
|
||||
|
||||
switch {
|
||||
case statusCode >= 200 && statusCode < 400:
|
||||
// it's a client error
|
||||
|
||||
@@ -44,7 +44,7 @@ all of the tests.
|
||||
- When running inside a Docker development container, `hack/make.sh` does
|
||||
not have a single target that runs all the tests. You need to provide a
|
||||
single command line with multiple targets that performs the same thing.
|
||||
An example referenced from [Run targets inside a development container](https://docs.docker.com/opensource/project/test-and-docs/#run-targets-inside-a-development-container): `root@5f8630b873fe:/go/src/github.com/moby/moby# hack/make.sh dynbinary binary cross test-unit test-integration test-docker-py`
|
||||
An example referenced from [Run targets inside a development container](https://docs.docker.com/opensource/project/test-and-docs/#run-targets-inside-a-development-container): `root@5f8630b873fe:/go/src/github.com/moby/moby# hack/make.sh dynbinary binary test-unit test-integration test-docker-py`
|
||||
- For more information related to testing outside the scope of this README,
|
||||
refer to
|
||||
[Run tests and test documentation](https://docs.docker.com/opensource/project/test-and-docs/)
|
||||
|
||||
@@ -9,11 +9,8 @@ if [ -n "$BUILDKIT_REF" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# prepare go mod
|
||||
./hack/go-mod-prepare.sh
|
||||
|
||||
# get buildkit version from vendor.mod
|
||||
BUILDKIT_REF=$(GO111MODULE=on go list -mod=mod -modfile=vendor.mod -u -m -f '{{.Version}}' "github.com/${BUILDKIT_REPO}")
|
||||
BUILDKIT_REF=$(./hack/with-go-mod.sh go list -mod=mod -modfile=vendor.mod -u -m -f '{{.Version}}' "github.com/${BUILDKIT_REPO}")
|
||||
if [[ "${BUILDKIT_REF}" == *-*-* ]]; then
|
||||
# if pseudo-version, figure out just the uncommon sha (https://github.com/golang/go/issues/34745)
|
||||
BUILDKIT_REF=$(echo "${BUILDKIT_REF}" | awk -F"-" '{print $NF}' | awk 'BEGIN{FIELDWIDTHS="7"} {print $1}')
|
||||
|
||||
@@ -15,7 +15,7 @@ set -e
|
||||
# the binary version you may also need to update the vendor version to pick up
|
||||
# bug fixes or new APIs, however, usually the Go packages are built from a
|
||||
# commit from the master branch.
|
||||
: "${CONTAINERD_VERSION:=v1.6.10}"
|
||||
: "${CONTAINERD_VERSION:=v1.6.16}"
|
||||
|
||||
install_containerd() (
|
||||
echo "Install containerd version $CONTAINERD_VERSION"
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
ROOTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
cat > "${ROOTDIR}/go.mod" << EOF
|
||||
module github.com/docker/docker
|
||||
|
||||
go 1.18
|
||||
EOF
|
||||
31
hack/make.sh
31
hack/make.sh
@@ -36,10 +36,17 @@ DEFAULT_BUNDLES=(
|
||||
dynbinary
|
||||
test-integration
|
||||
test-docker-py
|
||||
cross
|
||||
)
|
||||
|
||||
VERSION=${VERSION:-dev}
|
||||
if [[ $VERSION == refs/tags/* ]]; then
|
||||
VERSION=${VERSION#refs/tags/}
|
||||
elif [[ $VERSION == refs/heads/* ]]; then
|
||||
VERSION=$(sed <<< "${VERSION#refs/heads/}" -r 's#/+#-#g')
|
||||
elif [[ $VERSION == refs/pull/* ]]; then
|
||||
VERSION=pr-$(grep <<< "$VERSION" -o '[0-9]\+')
|
||||
fi
|
||||
|
||||
! BUILDTIME=$(date -u -d "@${SOURCE_DATE_EPOCH:-$(date +%s)}" --rfc-3339 ns 2> /dev/null | sed -e 's/ /T/')
|
||||
if [ "$DOCKER_GITCOMMIT" ]; then
|
||||
GITCOMMIT="$DOCKER_GITCOMMIT"
|
||||
@@ -93,34 +100,18 @@ fi
|
||||
# functionality. We favour libdm_dlsym_deferred_remove over
|
||||
# libdm_no_deferred_remove in dynamic cases because the binary could be shipped
|
||||
# with a newer libdevmapper than the one it was built with.
|
||||
if
|
||||
command -v gcc &> /dev/null \
|
||||
&& ! (echo -e '#include <libdevmapper.h>\nint main() { dm_task_deferred_remove(NULL); }' | gcc -xc - -o /dev/null $(pkg-config --libs devmapper) &> /dev/null) \
|
||||
;
|
||||
then
|
||||
if command -v gcc &> /dev/null && ! (echo -e '#include <libdevmapper.h>\nint main() { dm_task_deferred_remove(NULL); }' | gcc -xc - -o /dev/null $(${PKG_CONFIG} --libs devmapper 2> /dev/null) &> /dev/null); then
|
||||
add_buildtag libdm dlsym_deferred_remove
|
||||
fi
|
||||
|
||||
# Use these flags when compiling the tests and final binary
|
||||
|
||||
IAMSTATIC='true'
|
||||
if [ -z "$DOCKER_DEBUG" ]; then
|
||||
LDFLAGS='-w'
|
||||
fi
|
||||
|
||||
LDFLAGS_STATIC=''
|
||||
EXTLDFLAGS_STATIC='-static'
|
||||
# ORIG_BUILDFLAGS is necessary for the cross target which cannot always build
|
||||
# with options like -race.
|
||||
ORIG_BUILDFLAGS=(-tags "netgo osusergo static_build $DOCKER_BUILDTAGS" -installsuffix netgo)
|
||||
# see https://github.com/golang/go/issues/9369#issuecomment-69864440 for why -installsuffix is necessary here
|
||||
|
||||
BUILDFLAGS=(${BUILDFLAGS} "${ORIG_BUILDFLAGS[@]}")
|
||||
|
||||
LDFLAGS_STATIC_DOCKER="
|
||||
$LDFLAGS_STATIC
|
||||
-extldflags \"$EXTLDFLAGS_STATIC\"
|
||||
"
|
||||
BUILDFLAGS=(${BUILDFLAGS} -tags "netgo osusergo static_build $DOCKER_BUILDTAGS")
|
||||
LDFLAGS_STATIC="-extldflags -static"
|
||||
|
||||
if [ "$(uname -s)" = 'FreeBSD' ]; then
|
||||
# Tell cgo the compiler is Clang, not GCC
|
||||
|
||||
@@ -18,79 +18,55 @@ source "${MAKEDIR}/.go-autogen"
|
||||
|
||||
if [ "$(go env GOOS)/$(go env GOARCH)" != "$(go env GOHOSTOS)/$(go env GOHOSTARCH)" ]; then
|
||||
# must be cross-compiling!
|
||||
case "$(go env GOOS)/$(go env GOARCH)" in
|
||||
windows/amd64)
|
||||
export CC="${CC:-x86_64-w64-mingw32-gcc}"
|
||||
export CGO_ENABLED=1
|
||||
;;
|
||||
linux/arm)
|
||||
case "${GOARM}" in
|
||||
5)
|
||||
export CC="${CC:-arm-linux-gnueabi-gcc}"
|
||||
export CGO_ENABLED=1
|
||||
export CGO_CFLAGS="-march=armv5t"
|
||||
export CGO_CXXFLAGS="-march=armv5t"
|
||||
;;
|
||||
6)
|
||||
export CC="${CC:-arm-linux-gnueabi-gcc}"
|
||||
export CGO_ENABLED=1
|
||||
export CGO_CFLAGS="-march=armv6"
|
||||
export CGO_CXXFLAGS="-march=armv6"
|
||||
;;
|
||||
7)
|
||||
export CC="${CC:-arm-linux-gnueabihf-gcc}"
|
||||
export CGO_ENABLED=1
|
||||
export CGO_CFLAGS="-march=armv7-a"
|
||||
export CGO_CXXFLAGS="-march=armv7-a"
|
||||
;;
|
||||
*)
|
||||
export CC="${CC:-arm-linux-gnueabihf-gcc}"
|
||||
export CGO_ENABLED=1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
linux/arm64)
|
||||
export CC="${CC:-aarch64-linux-gnu-gcc}"
|
||||
export CGO_ENABLED=1
|
||||
;;
|
||||
linux/amd64)
|
||||
export CC="${CC:-x86_64-linux-gnu-gcc}"
|
||||
export CGO_ENABLED=1
|
||||
;;
|
||||
linux/ppc64le)
|
||||
export CC="${CC:-powerpc64le-linux-gnu-gcc}"
|
||||
export CGO_ENABLED=1
|
||||
;;
|
||||
linux/s390x)
|
||||
export CC="${CC:-s390x-linux-gnu-gcc}"
|
||||
export CGO_ENABLED=1
|
||||
;;
|
||||
esac
|
||||
if [ "$(go env GOOS)/$(go env GOARCH)" = "linux/arm" ]; then
|
||||
# specify name of the target ARM architecture
|
||||
case "$(go env GOARM)" in
|
||||
5)
|
||||
export CGO_CFLAGS="-march=armv5t"
|
||||
export CGO_CXXFLAGS="-march=armv5t"
|
||||
;;
|
||||
6)
|
||||
export CGO_CFLAGS="-march=armv6"
|
||||
export CGO_CXXFLAGS="-march=armv6"
|
||||
;;
|
||||
7)
|
||||
export CGO_CFLAGS="-march=armv7-a"
|
||||
export CGO_CXXFLAGS="-march=armv7-a"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
# -buildmode=pie is not supported on Windows and Linux on mips, riscv64 and ppc64be.
|
||||
# https://github.com/golang/go/blob/77aa209b386a184e7f4b44938f2a05a1b5c5a3cf/src/cmd/internal/sys/supported.go#L89-L99
|
||||
case "$(go env GOOS)/$(go env GOARCH)" in
|
||||
windows/* | linux/mips* | linux/riscv* | linux/ppc64) ;;
|
||||
# TODO remove windows in Go 1.15+: https://github.com/golang/go/commit/95f382139043059a2a0780ba577b53893408f7e4
|
||||
# TODO remove riscv64 in Go 1.16+: https://github.com/golang/go/commit/8eb846fd37eb7bded8a1cf6932be2c59069863e5
|
||||
# -buildmode=pie is not supported on Windows arm64 and Linux mips*, ppc64be
|
||||
# https://github.com/golang/go/blob/go1.19.4/src/cmd/internal/sys/supported.go#L125-L132
|
||||
if ! [ "$DOCKER_STATIC" = "1" ]; then
|
||||
# -buildmode=pie not supported when -race is enabled
|
||||
if [[ " $BUILDFLAGS " != *" -race "* ]]; then
|
||||
case "$(go env GOOS)/$(go env GOARCH)" in
|
||||
windows/arm64 | linux/mips* | linux/ppc64) ;;
|
||||
*)
|
||||
BUILDFLAGS+=("-buildmode=pie")
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
*)
|
||||
BUILDFLAGS+=("-buildmode=pie")
|
||||
;;
|
||||
esac
|
||||
# only necessary for non-sandboxed invocation where TARGETPLATFORM is empty
|
||||
PLATFORM_NAME=$TARGETPLATFORM
|
||||
if [ -z "$PLATFORM_NAME" ]; then
|
||||
PLATFORM_NAME="$(go env GOOS)/$(go env GOARCH)"
|
||||
if [ -n "$(go env GOARM)" ]; then
|
||||
PLATFORM_NAME+="/v$(go env GOARM)"
|
||||
elif [ -n "$(go env GOAMD64)" ] && [ "$(go env GOAMD64)" != "v1" ]; then
|
||||
PLATFORM_NAME+="/$(go env GOAMD64)"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Building: $DEST/$BINARY_FULLNAME"
|
||||
echo "GOOS=\"${GOOS}\" GOARCH=\"${GOARCH}\" GOARM=\"${GOARM}\""
|
||||
go build \
|
||||
-o "$DEST/$BINARY_FULLNAME" \
|
||||
"${BUILDFLAGS[@]}" \
|
||||
-ldflags "
|
||||
$LDFLAGS
|
||||
$LDFLAGS_STATIC_DOCKER
|
||||
$DOCKER_LDFLAGS
|
||||
" \
|
||||
${GO_PACKAGE}
|
||||
echo "Building $([ "$DOCKER_STATIC" = "1" ] && echo "static" || echo "dynamic") $DEST/$BINARY_FULLNAME ($PLATFORM_NAME)..."
|
||||
if [ -n "$DOCKER_DEBUG" ]; then
|
||||
set -x
|
||||
fi
|
||||
go build -o "$DEST/$BINARY_FULLNAME" "${BUILDFLAGS[@]}" -ldflags "$LDFLAGS $LDFLAGS_STATIC $DOCKER_LDFLAGS" ${GO_PACKAGE}
|
||||
)
|
||||
|
||||
echo "Created binary: $DEST/$BINARY_FULLNAME"
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
LDFLAGS="${LDFLAGS} \
|
||||
-X \"github.com/docker/docker/dockerversion.Version=${VERSION}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.GitCommit=${GITCOMMIT}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.BuildTime=${BUILDTIME}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.IAmStatic=${IAMSTATIC:-true}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.PlatformName=${PLATFORM}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.ProductName=${PRODUCT}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.DefaultProductLicense=${DEFAULT_PRODUCT_LICENSE}\" \
|
||||
"
|
||||
-X \"github.com/docker/docker/dockerversion.Version=${VERSION}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.GitCommit=${GITCOMMIT}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.BuildTime=${BUILDTIME}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.PlatformName=${PLATFORM}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.ProductName=${PRODUCT}\" \
|
||||
-X \"github.com/docker/docker/dockerversion.DefaultProductLicense=${DEFAULT_PRODUCT_LICENSE}\" "
|
||||
|
||||
# Compile the Windows resources into the sources
|
||||
if [ "$(go env GOOS)" = "windows" ]; then
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
set -e
|
||||
|
||||
copy_binaries() {
|
||||
local dir="$1"
|
||||
local dir="${1:?}"
|
||||
|
||||
# Add nested executables to bundle dir so we have complete set of
|
||||
# them available, but only if the native OS/ARCH is the same as the
|
||||
@@ -27,9 +27,9 @@ copy_binaries() {
|
||||
[ -z "$KEEPDEST" ] && rm -rf "$DEST"
|
||||
|
||||
(
|
||||
DOCKER_STATIC=1
|
||||
GO_PACKAGE='github.com/docker/docker/cmd/dockerd'
|
||||
BINARY_NAME='dockerd'
|
||||
|
||||
source "${MAKEDIR}/.binary"
|
||||
copy_binaries "$DEST"
|
||||
)
|
||||
|
||||
@@ -5,8 +5,8 @@ set -e
|
||||
(
|
||||
export CGO_ENABLED=0
|
||||
|
||||
DOCKER_STATIC=1
|
||||
GO_PACKAGE='github.com/docker/docker/cmd/docker-proxy'
|
||||
BINARY_NAME='docker-proxy'
|
||||
|
||||
source "${MAKEDIR}/.binary"
|
||||
)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
: "${CONTAINER_UTILITY_COMMIT:=aa1ba87e99b68e0113bd27ec26c60b88f9d4ccd9}"
|
||||
|
||||
(
|
||||
git clone https://github.com/docker/windows-container-utility.git "$GOPATH/src/github.com/docker/windows-container-utility"
|
||||
cd "$GOPATH/src/github.com/docker/windows-container-utility"
|
||||
git checkout -q "$CONTAINER_UTILITY_COMMIT"
|
||||
|
||||
echo Building: ${DEST}/containerutility.exe
|
||||
|
||||
(
|
||||
make
|
||||
)
|
||||
|
||||
mkdir -p ${ABS_DEST}
|
||||
|
||||
cp containerutility.exe ${ABS_DEST}/containerutility.exe
|
||||
)
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# if we have our linux/amd64 version compiled, let's symlink it in
|
||||
if [ -x "${DEST}/../binary-daemon/dockerd" ]; then
|
||||
arch=$(go env GOHOSTARCH)
|
||||
mkdir -p "$DEST/linux/${arch}"
|
||||
(
|
||||
cd "${DEST}/linux/${arch}"
|
||||
ln -sf ../../../binary-daemon/* ./
|
||||
)
|
||||
echo "Created symlinks:" "${DEST}/linux/${arch}/"*
|
||||
fi
|
||||
|
||||
DOCKER_CROSSPLATFORMS=${DOCKER_CROSSPLATFORMS:-"linux/amd64 windows/amd64 linux/ppc64le linux/s390x"}
|
||||
|
||||
for platform in ${DOCKER_CROSSPLATFORMS}; do
|
||||
(
|
||||
export KEEPDEST=1
|
||||
export DEST="${DEST}/${platform}" # bundles/VERSION/cross/GOOS/GOARCH/docker-VERSION
|
||||
export GOOS=${platform%%/*}
|
||||
export GOARCH=${platform#*/}
|
||||
|
||||
if [[ "${GOARCH}" = "arm/"* ]]; then
|
||||
GOARM=${GOARCH##*/v}
|
||||
GOARCH=${GOARCH%/v*}
|
||||
export GOARM
|
||||
fi
|
||||
|
||||
echo "Cross building: ${DEST}"
|
||||
mkdir -p "${DEST}"
|
||||
ABS_DEST="$(cd "${DEST}" && pwd -P)"
|
||||
source "${MAKEDIR}/binary"
|
||||
|
||||
source "${MAKEDIR}/cross-platform-dependent"
|
||||
)
|
||||
done
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
if [ ${platform} == "windows/amd64" ]; then
|
||||
source "${MAKEDIR}/containerutility"
|
||||
fi
|
||||
@@ -4,8 +4,7 @@ set -e
|
||||
[ -z "$KEEPDEST" ] && rm -rf "$DEST"
|
||||
|
||||
(
|
||||
export IAMSTATIC='false'
|
||||
export LDFLAGS_STATIC_DOCKER=''
|
||||
export LDFLAGS_STATIC=''
|
||||
export BUILDFLAGS=("${BUILDFLAGS[@]/netgo /}") # disable netgo, since we don't need it for a dynamic binary
|
||||
export BUILDFLAGS=("${BUILDFLAGS[@]/osusergo /}") # ditto for osusergo
|
||||
export BUILDFLAGS=("${BUILDFLAGS[@]/static_build /}") # we're not building a "static" binary here
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
set -e
|
||||
|
||||
(
|
||||
export IAMSTATIC='false'
|
||||
export LDFLAGS_STATIC_DOCKER=''
|
||||
export LDFLAGS_STATIC=''
|
||||
export BUILDFLAGS=("${BUILDFLAGS[@]/netgo /}") # disable netgo, since we don't need it for a dynamic binary
|
||||
export BUILDFLAGS=("${BUILDFLAGS[@]/osusergo /}") # ditto for osusergo
|
||||
export BUILDFLAGS=("${BUILDFLAGS[@]/static_build /}") # we're not building a "static" binary here
|
||||
|
||||
17
hack/validate/no-module
Executable file
17
hack/validate/no-module
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Check that no one is trying to commit a go.mod.
|
||||
|
||||
SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOTDIR="$(git -C "$SCRIPTDIR" rev-parse --show-toplevel)"
|
||||
|
||||
if test -e "${ROOTDIR}/go.mod"; then
|
||||
{
|
||||
echo 'FAIL: go.mod found in repository root!'
|
||||
echo
|
||||
echo ' Moby is not a Go module; please delete go.mod and try again.'
|
||||
} >&2
|
||||
exit 1
|
||||
else
|
||||
echo 'PASS: No go.mod found in repository root!'
|
||||
fi
|
||||
@@ -1,53 +1,55 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPTDIR}/.validate"
|
||||
|
||||
tidy_files=('vendor.mod' 'vendor.sum')
|
||||
vendor_files=("${tidy_files[@]}" 'vendor/')
|
||||
|
||||
validate_vendor_tidy() {
|
||||
# run mod tidy
|
||||
./hack/vendor.sh tidy
|
||||
# check if any files have changed
|
||||
git diff --quiet HEAD -- "${tidy_files[@]}"
|
||||
}
|
||||
|
||||
validate_vendor_diff() {
|
||||
IFS=$'\n'
|
||||
check_files=('vendor.sum' 'vendor.mod' 'vendor/')
|
||||
# shellcheck disable=SC2207
|
||||
changed_files=($(validate_diff --diff-filter=ACMR --name-only -- "${check_files[@]}" || true))
|
||||
unset IFS
|
||||
mapfile -t changed_files < <(validate_diff --diff-filter=ACMR --name-only -- "${vendor_files[@]}")
|
||||
|
||||
if [ -n "${TEST_FORCE_VALIDATE:-}" ] || [ "${#changed_files[@]}" -gt 0 ]; then
|
||||
# recreate vendor/
|
||||
./hack/vendor.sh
|
||||
./hack/vendor.sh vendor
|
||||
# check if any files have changed
|
||||
diffs="$(git status --porcelain -- "${check_files[@]}" 2> /dev/null)"
|
||||
mfiles="$(echo "$diffs" | awk '/^ M / {print $2}')"
|
||||
if [ "$diffs" ]; then
|
||||
{
|
||||
echo 'The result of go mod vendor differs'
|
||||
echo
|
||||
echo "$diffs"
|
||||
echo
|
||||
echo 'Please vendor your package with hack/vendor.sh.'
|
||||
echo
|
||||
if [ -n "$mfiles" ]; then
|
||||
git diff -- "$mfiles"
|
||||
fi
|
||||
} >&2
|
||||
false
|
||||
else
|
||||
echo 'Congratulations! All vendoring changes are done the right way.'
|
||||
fi
|
||||
git diff --quiet HEAD -- "${vendor_files[@]}"
|
||||
else
|
||||
echo 'No vendor changes in diff.'
|
||||
echo >&2 'INFO: no vendor changes in diff; skipping vendor check.'
|
||||
fi
|
||||
}
|
||||
|
||||
# 1. make sure all the vendored packages are used
|
||||
# 2. make sure all the packages contain license information (just warning, because it can cause false-positive)
|
||||
validate_vendor_used() {
|
||||
for f in $(mawk '$1 = "#" { print $2 }' 'vendor/modules.txt'); do
|
||||
if [ -d "vendor/$f" ]; then
|
||||
if ! echo "vendor/$f"/* | grep -qiEc '/(LICENSE|COPYING)'; then
|
||||
echo "WARNING: could not find copyright information for $f"
|
||||
fi
|
||||
validate_vendor_license() {
|
||||
while IFS= read -r module; do
|
||||
test -d "vendor/$module" || continue
|
||||
if ! compgen -G "vendor/$module/*" | grep -qEi '/(LICENSE|COPYING)[^/]*$'; then
|
||||
echo >&2 "WARNING: could not find copyright information for $module"
|
||||
fi
|
||||
done
|
||||
done < <(awk '/^# /{ print $2 }' vendor/modules.txt)
|
||||
}
|
||||
|
||||
validate_vendor_diff
|
||||
validate_vendor_used
|
||||
if validate_vendor_tidy && validate_vendor_diff && validate_vendor_license; then
|
||||
echo >&2 'PASS: Vendoring has been performed correctly!'
|
||||
else
|
||||
{
|
||||
echo 'FAIL: Vendoring was not performed correctly!'
|
||||
echo
|
||||
echo 'The following files changed during re-vendor:'
|
||||
echo
|
||||
git diff --name-status HEAD -- "${vendor_files[@]}"
|
||||
echo
|
||||
echo 'Please revendor with hack/vendor.sh'
|
||||
echo
|
||||
git diff --diff-filter=M -- "${vendor_files[@]}"
|
||||
} >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -1,14 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This file is just wrapper around 'go mod vendor' tool.
|
||||
#
|
||||
# This file is just a wrapper around the 'go mod vendor' tool.
|
||||
# For updating dependencies you should change `vendor.mod` file in root of the
|
||||
# project.
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
"${SCRIPTDIR}"/go-mod-prepare.sh
|
||||
|
||||
GO111MODULE=auto go mod tidy -modfile 'vendor.mod' -compat 1.18
|
||||
GO111MODULE=auto go mod vendor -modfile vendor.mod
|
||||
tidy() (
|
||||
set -x
|
||||
"${SCRIPTDIR}"/with-go-mod.sh go mod tidy -modfile vendor.mod -compat 1.18
|
||||
)
|
||||
|
||||
vendor() (
|
||||
set -x
|
||||
"${SCRIPTDIR}"/with-go-mod.sh go mod vendor -modfile vendor.mod
|
||||
)
|
||||
|
||||
help() {
|
||||
printf "%s:\n" "$(basename "$0")"
|
||||
echo " - tidy: run go mod tidy"
|
||||
echo " - vendor: run go mod vendor"
|
||||
echo " - all: run tidy && vendor"
|
||||
echo " - help: show this help"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
tidy) tidy ;;
|
||||
vendor) vendor ;;
|
||||
""|all) tidy && vendor ;;
|
||||
*) help ;;
|
||||
esac
|
||||
|
||||
31
hack/with-go-mod.sh
Executable file
31
hack/with-go-mod.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# This script is used to coerce certain commands which rely on the presence of
|
||||
# a go.mod into working with our repository. It works by creating a fake
|
||||
# go.mod, running a specified command (passed via arguments), and removing it
|
||||
# when the command is finished. This script should be dropped when this
|
||||
# repository is a proper Go module with a permanent go.mod.
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOTDIR="$(git -C "$SCRIPTDIR" rev-parse --show-toplevel)"
|
||||
|
||||
if test -e "${ROOTDIR}/go.mod"; then
|
||||
{
|
||||
scriptname=$(basename "$0")
|
||||
echo "${scriptname}: WARN: go.mod exists in the repository root!"
|
||||
echo "${scriptname}: WARN: Using your go.mod instead of our generated version -- this may misbehave!"
|
||||
} >&2
|
||||
else
|
||||
set -x
|
||||
|
||||
tee "${ROOTDIR}/go.mod" >&2 <<- EOF
|
||||
module github.com/docker/docker
|
||||
|
||||
go 1.18
|
||||
EOF
|
||||
trap 'rm -f "${ROOTDIR}/go.mod"' EXIT
|
||||
fi
|
||||
|
||||
GO111MODULE=on "$@"
|
||||
@@ -56,11 +56,11 @@ func newFSStore(root string) (*fs, error) {
|
||||
}
|
||||
|
||||
func (s *fs) contentFile(dgst digest.Digest) string {
|
||||
return filepath.Join(s.root, contentDirName, string(dgst.Algorithm()), dgst.Hex())
|
||||
return filepath.Join(s.root, contentDirName, string(dgst.Algorithm()), dgst.Encoded())
|
||||
}
|
||||
|
||||
func (s *fs) metadataDir(dgst digest.Digest) string {
|
||||
return filepath.Join(s.root, metadataDirName, string(dgst.Algorithm()), dgst.Hex())
|
||||
return filepath.Join(s.root, metadataDirName, string(dgst.Algorithm()), dgst.Encoded())
|
||||
}
|
||||
|
||||
// Walk calls the supplied callback for each image ID in the storage backend.
|
||||
@@ -73,7 +73,7 @@ func (s *fs) Walk(f DigestWalkFunc) error {
|
||||
return err
|
||||
}
|
||||
for _, v := range dir {
|
||||
dgst := digest.NewDigestFromHex(string(digest.Canonical), v.Name())
|
||||
dgst := digest.NewDigestFromEncoded(digest.Canonical, v.Name())
|
||||
if err := dgst.Validate(); err != nil {
|
||||
logrus.Debugf("skipping invalid digest %s: %s", dgst, err)
|
||||
continue
|
||||
|
||||
@@ -31,7 +31,7 @@ func TestFSGetInvalidData(t *testing.T) {
|
||||
dgst, err := store.Set([]byte("foobar"))
|
||||
assert.Check(t, err)
|
||||
|
||||
err = os.WriteFile(filepath.Join(store.(*fs).root, contentDirName, string(dgst.Algorithm()), dgst.Hex()), []byte("foobar2"), 0600)
|
||||
err = os.WriteFile(filepath.Join(store.(*fs).root, contentDirName, string(dgst.Algorithm()), dgst.Encoded()), []byte("foobar2"), 0o600)
|
||||
assert.Check(t, err)
|
||||
|
||||
_, err = store.Get(dgst)
|
||||
@@ -43,7 +43,7 @@ func TestFSInvalidSet(t *testing.T) {
|
||||
defer cleanup()
|
||||
|
||||
id := digest.FromBytes([]byte("foobar"))
|
||||
err := os.Mkdir(filepath.Join(store.(*fs).root, contentDirName, string(id.Algorithm()), id.Hex()), 0700)
|
||||
err := os.Mkdir(filepath.Join(store.(*fs).root, contentDirName, string(id.Algorithm()), id.Encoded()), 0o700)
|
||||
assert.Check(t, err)
|
||||
|
||||
_, err = store.Set([]byte("foobar"))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user