1{ lib, callPackage }:
2
3rec {
4 dockerGen =
5 {
6 version,
7 cliRev,
8 cliHash,
9 mobyRev,
10 mobyHash,
11 runcRev,
12 runcHash,
13 containerdRev,
14 containerdHash,
15 tiniRev,
16 tiniHash,
17 buildxSupport ? true,
18 composeSupport ? true,
19 sbomSupport ? false,
20 initSupport ? false,
21 # package dependencies
22 stdenv,
23 fetchFromGitHub,
24 fetchpatch,
25 buildGoModule,
26 makeWrapper,
27 installShellFiles,
28 pkg-config,
29 glibc,
30 go-md2man,
31 go,
32 containerd,
33 runc,
34 tini,
35 libtool,
36 bash,
37 sqlite,
38 iproute2,
39 docker-buildx,
40 docker-compose,
41 docker-sbom,
42 docker-init,
43 iptables,
44 e2fsprogs,
45 xz,
46 util-linux,
47 xfsprogs,
48 gitMinimal,
49 procps,
50 rootlesskit,
51 slirp4netns,
52 fuse-overlayfs,
53 nixosTests,
54 clientOnly ? !stdenv.hostPlatform.isLinux,
55 symlinkJoin,
56 withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
57 systemd,
58 withBtrfs ? stdenv.hostPlatform.isLinux,
59 btrfs-progs,
60 withLvm ? stdenv.hostPlatform.isLinux,
61 lvm2,
62 withSeccomp ? stdenv.hostPlatform.isLinux,
63 libseccomp,
64 knownVulnerabilities ? [ ],
65 }:
66 let
67 docker-meta = {
68 license = lib.licenses.asl20;
69 maintainers = with lib.maintainers; [
70 offline
71 vdemeester
72 periklis
73 teutat3s
74 ];
75 };
76
77 docker-runc = runc.overrideAttrs {
78 pname = "docker-runc";
79 inherit version;
80
81 src = fetchFromGitHub {
82 owner = "opencontainers";
83 repo = "runc";
84 rev = runcRev;
85 hash = runcHash;
86 };
87
88 preBuild = ''
89 substituteInPlace Makefile --replace-warn "/bin/bash" "${stdenv.shell}"
90 '';
91
92 # docker/runc already include these patches / are not applicable
93 patches = [ ];
94 };
95
96 docker-containerd = containerd.overrideAttrs (oldAttrs: {
97 pname = "docker-containerd";
98 inherit version;
99
100 # We only need binaries
101 outputs = [ "out" ];
102
103 src = fetchFromGitHub {
104 owner = "containerd";
105 repo = "containerd";
106 rev = containerdRev;
107 hash = containerdHash;
108 };
109
110 buildInputs = oldAttrs.buildInputs ++ lib.optionals withSeccomp [ libseccomp ];
111
112 # See above
113 installTargets = "install";
114 });
115
116 docker-tini = tini.overrideAttrs {
117 pname = "docker-init";
118 inherit version;
119
120 src = fetchFromGitHub {
121 owner = "krallin";
122 repo = "tini";
123 rev = tiniRev;
124 hash = tiniHash;
125 };
126
127 # Do not remove static from make files as we want a static binary
128 postPatch = "";
129
130 buildInputs = [
131 glibc
132 glibc.static
133 ];
134
135 env.NIX_CFLAGS_COMPILE = "-DMINIMAL=ON";
136 };
137
138 moby-src = fetchFromGitHub {
139 owner = "moby";
140 repo = "moby";
141 rev = mobyRev;
142 hash = mobyHash;
143 };
144
145 moby = buildGoModule (
146 lib.optionalAttrs stdenv.hostPlatform.isLinux rec {
147 pname = "moby";
148 inherit version;
149
150 src = moby-src;
151
152 vendorHash = null;
153
154 nativeBuildInputs = [
155 makeWrapper
156 pkg-config
157 go-md2man
158 go
159 libtool
160 installShellFiles
161 ];
162 buildInputs = [
163 sqlite
164 ]
165 ++ lib.optional withLvm lvm2
166 ++ lib.optional withBtrfs btrfs-progs
167 ++ lib.optional withSystemd systemd
168 ++ lib.optional withSeccomp libseccomp;
169
170 extraPath = lib.optionals stdenv.hostPlatform.isLinux (
171 lib.makeBinPath [
172 iproute2
173 iptables
174 e2fsprogs
175 xz
176 xfsprogs
177 procps
178 util-linux
179 gitMinimal
180 ]
181 );
182
183 extraUserPath = lib.optionals (stdenv.hostPlatform.isLinux && !clientOnly) (
184 lib.makeBinPath [
185 rootlesskit
186 slirp4netns
187 fuse-overlayfs
188 ]
189 );
190
191 postPatch = ''
192 patchShebangs hack/make.sh hack/make/ hack/with-go-mod.sh
193 '';
194
195 buildPhase = ''
196 export GOCACHE="$TMPDIR/go-cache"
197 # build engine
198 export AUTO_GOPATH=1
199 export DOCKER_GITCOMMIT="${cliRev}"
200 export VERSION="${version}"
201 ./hack/make.sh dynbinary
202 '';
203
204 installPhase = ''
205 install -Dm755 ./bundles/dynbinary-daemon/dockerd $out/libexec/docker/dockerd
206 install -Dm755 ./bundles/dynbinary-daemon/docker-proxy $out/libexec/docker/docker-proxy
207
208 makeWrapper $out/libexec/docker/dockerd $out/bin/dockerd \
209 --prefix PATH : "$out/libexec/docker:$extraPath"
210
211 ln -s ${docker-containerd}/bin/containerd $out/libexec/docker/containerd
212 ln -s ${docker-containerd}/bin/containerd-shim $out/libexec/docker/containerd-shim
213 ln -s ${docker-runc}/bin/runc $out/libexec/docker/runc
214 ln -s ${docker-tini}/bin/tini-static $out/libexec/docker/docker-init
215
216 # systemd
217 install -Dm644 ./contrib/init/systemd/docker.service $out/etc/systemd/system/docker.service
218 substituteInPlace $out/etc/systemd/system/docker.service --replace-fail /usr/bin/dockerd $out/bin/dockerd
219 install -Dm644 ./contrib/init/systemd/docker.socket $out/etc/systemd/system/docker.socket
220
221 # rootless Docker
222 install -Dm755 ./contrib/dockerd-rootless.sh $out/libexec/docker/dockerd-rootless.sh
223 makeWrapper $out/libexec/docker/dockerd-rootless.sh $out/bin/dockerd-rootless \
224 --prefix PATH : "$out/libexec/docker:$extraPath:$extraUserPath"
225 '';
226
227 DOCKER_BUILDTAGS =
228 lib.optional withSystemd "journald"
229 ++ lib.optional (!withBtrfs) "exclude_graphdriver_btrfs"
230 ++ lib.optional (!withLvm) "exclude_graphdriver_devicemapper"
231 ++ lib.optional withSeccomp "seccomp";
232
233 meta = docker-meta // {
234 homepage = "https://mobyproject.org/";
235 description = "Collaborative project for the container ecosystem to assemble container-based systems";
236 };
237 }
238 );
239
240 plugins =
241 lib.optional buildxSupport docker-buildx
242 ++ lib.optional composeSupport docker-compose
243 ++ lib.optional sbomSupport docker-sbom
244 ++ lib.optional initSupport docker-init;
245 pluginsRef = symlinkJoin {
246 name = "docker-plugins";
247 paths = plugins;
248 };
249 in
250 buildGoModule (
251 lib.optionalAttrs (!clientOnly) {
252 # allow overrides of docker components
253 # TODO: move packages out of the let...in into top-level to allow proper overrides
254 inherit
255 docker-runc
256 docker-containerd
257 docker-tini
258 moby
259 ;
260 }
261 // rec {
262 pname = "docker";
263 inherit version;
264
265 src = fetchFromGitHub {
266 owner = "docker";
267 repo = "cli";
268 rev = cliRev;
269 hash = cliHash;
270 };
271
272 vendorHash = null;
273
274 nativeBuildInputs = [
275 makeWrapper
276 pkg-config
277 go-md2man
278 go
279 libtool
280 installShellFiles
281 ];
282
283 buildInputs =
284 plugins
285 ++ lib.optionals (stdenv.hostPlatform.isLinux) [
286 glibc
287 glibc.static
288 ];
289
290 postPatch = ''
291 patchShebangs man scripts/build/
292 substituteInPlace ./scripts/build/.variables --replace-fail "set -eu" ""
293 ''
294 + lib.optionalString (plugins != [ ]) ''
295 substituteInPlace ./cli-plugins/manager/manager_unix.go --replace-fail /usr/libexec/docker/cli-plugins \
296 "${pluginsRef}/libexec/docker/cli-plugins"
297 '';
298
299 # Keep eyes on BUILDTIME format - https://github.com/docker/cli/blob/${version}/scripts/build/.variables
300 buildPhase = ''
301 export GOCACHE="$TMPDIR/go-cache"
302
303 # Mimic AUTO_GOPATH
304 mkdir -p .gopath/src/github.com/docker/
305 ln -sf $PWD .gopath/src/github.com/docker/cli
306 export GOPATH="$PWD/.gopath:$GOPATH"
307 export GITCOMMIT="${cliRev}"
308 export VERSION="${version}"
309 export BUILDTIME="1970-01-01T00:00:00Z"
310 make dynbinary
311
312 '';
313
314 outputs = [ "out" ];
315
316 installPhase = ''
317 runHook preInstall
318
319 install -Dm755 ./build/docker $out/libexec/docker/docker
320
321 makeWrapper $out/libexec/docker/docker $out/bin/docker \
322 --prefix PATH : "$out/libexec/docker:$extraPath"
323 ''
324 + lib.optionalString (!clientOnly) ''
325 # symlink docker daemon to docker cli derivation
326 ln -s ${moby}/bin/dockerd $out/bin/dockerd
327 ln -s ${moby}/bin/dockerd-rootless $out/bin/dockerd-rootless
328
329 # systemd
330 mkdir -p $out/etc/systemd/system
331 ln -s ${moby}/etc/systemd/system/docker.service $out/etc/systemd/system/docker.service
332 ln -s ${moby}/etc/systemd/system/docker.socket $out/etc/systemd/system/docker.socket
333 ''
334 # Required to avoid breaking cross builds
335 + lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
336 # completion (cli)
337 installShellCompletion --cmd docker \
338 --bash <($out/bin/docker completion bash) \
339 --fish <($out/bin/docker completion fish) \
340 --zsh <($out/bin/docker completion zsh)
341 ''
342 + ''
343 runHook postInstall
344 '';
345
346 passthru = {
347 # Exposed for tarsum build on non-linux systems (build-support/docker/default.nix)
348 inherit moby-src;
349 tests = lib.optionalAttrs (!clientOnly) { inherit (nixosTests) docker; };
350 };
351
352 meta = docker-meta // {
353 homepage = "https://www.docker.com/";
354 description = "Open source project to pack, ship and run any application as a lightweight container";
355 longDescription = ''
356 Docker is a platform designed to help developers build, share, and run modern applications.
357
358 To enable the docker daemon on NixOS, set the `virtualisation.docker.enable` option to `true`.
359 '';
360 mainProgram = "docker";
361 inherit knownVulnerabilities;
362 };
363 }
364 );
365
366 # Get revisions from
367 # https://github.com/moby/moby/tree/${version}/hack/dockerfile/install/*
368 docker_25 = callPackage dockerGen rec {
369 version = "25.0.11";
370 # Upstream forgot to tag release
371 # https://github.com/docker/cli/issues/5789
372 cliRev = "43987fca488a535d810c429f75743d8c7b63bf4f";
373 cliHash = "sha256-OwufdfuUPbPtgqfPeiKrQVkOOacU2g4ommHb770gV40=";
374 mobyRev = "v${version}";
375 mobyHash = "sha256-vHHi0/sX9fm83gyUjDpRYTGV9h18IVia1oSmj4n31nc=";
376 runcRev = "v1.2.5";
377 runcHash = "sha256-J/QmOZxYnMPpzm87HhPTkYdt+fN+yeSUu2sv6aUeTY4=";
378 containerdRev = "v1.7.27";
379 containerdHash = "sha256-H94EHnfW2Z59KcHcbfJn+BipyZiNUvHe50G5EXbrIps=";
380 tiniRev = "v0.19.0";
381 tiniHash = "sha256-ZDKu/8yE5G0RYFJdhgmCdN3obJNyRWv6K/Gd17zc1sI=";
382 };
383
384 docker_28 = callPackage dockerGen rec {
385 version = "28.3.2";
386 cliRev = "v${version}";
387 cliHash = "sha256-LsV9roOPw0LccvBUeF3bY014OwG6QpnVsLf+dqKyvsg=";
388 mobyRev = "v${version}";
389 mobyHash = "sha256-YfdnCAc9NgLTuvxLHGhTPdWqXz9VSVsQsfzLD3YER3g=";
390 runcRev = "v1.2.6";
391 runcHash = "sha256-XMN+YKdQOQeOLLwvdrC6Si2iAIyyHD5RgZbrOHrQE/g=";
392 containerdRev = "v1.7.27";
393 containerdHash = "sha256-H94EHnfW2Z59KcHcbfJn+BipyZiNUvHe50G5EXbrIps=";
394 tiniRev = "v0.19.0";
395 tiniHash = "sha256-ZDKu/8yE5G0RYFJdhgmCdN3obJNyRWv6K/Gd17zc1sI=";
396 };
397
398}