1
+ # syntax=docker/dockerfile:1
2
+ # Enables BuildKit with cache mounts for faster builds
1
3
FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.25 AS builder
2
4
3
5
ARG TARGETOS TARGETARCH
4
6
5
7
ENV SRC_DIR=/kubo
6
8
7
- # Download packages first so they can be cached.
9
+ # Cache go module downloads between builds for faster rebuilds
8
10
COPY go.mod go.sum $SRC_DIR/
9
- RUN cd $SRC_DIR \
11
+ RUN --mount=type=cache,target=/go/pkg/mod \
12
+ cd $SRC_DIR \
10
13
&& go mod download
11
14
12
15
COPY . $SRC_DIR
@@ -18,92 +21,79 @@ ARG IPFS_PLUGINS
18
21
# Allow for other targets to be built, e.g.: docker build --build-arg MAKE_TARGET="nofuse"
19
22
ARG MAKE_TARGET=build
20
23
21
- # Build the thing.
22
- # Also: fix getting HEAD commit hash via git rev-parse.
23
- RUN cd $SRC_DIR \
24
+ # Build ipfs binary with cached go modules and build cache.
25
+ # mkdir .git/objects allows git rev-parse to read commit hash for version info
26
+ RUN --mount=type=cache,target=/go/pkg/mod \
27
+ --mount=type=cache,target=/root/.cache/go-build \
28
+ cd $SRC_DIR \
24
29
&& mkdir -p .git/objects \
25
30
&& GOOS=$TARGETOS GOARCH=$TARGETARCH GOFLAGS=-buildvcs=false make ${MAKE_TARGET} IPFS_PLUGINS=$IPFS_PLUGINS
26
31
27
- # Using Debian Buster because the version of busybox we're using is based on it
28
- # and we want to make sure the libraries we're using are compatible. That's also
29
- # why we're running this for the target platform .
32
+ # Extract required runtime tools from Debian.
33
+ # We use Debian instead of Alpine because we need glibc compatibility
34
+ # for the busybox base image we're using .
30
35
FROM debian:bookworm-slim AS utilities
31
36
RUN set -eux; \
32
37
apt-get update; \
33
- apt-get install -y \
38
+ apt-get install -y --no-install-recommends \
34
39
tini \
35
40
# Using gosu (~2MB) instead of su-exec (~20KB) because it's easier to
36
41
# install on Debian. Useful links:
37
42
# - https://github.com/ncopa/su-exec#why-reinvent-gosu
38
43
# - https://github.com/tianon/gosu/issues/52#issuecomment-441946745
39
44
gosu \
40
- # This installs fusermount which we later copy over to the target image.
45
+ # fusermount enables IPFS mount commands
41
46
fuse \
42
47
ca-certificates \
43
48
; \
44
- rm -rf /var/lib/apt/lists/*
49
+ apt-get clean; \
50
+ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
45
51
46
- # Now comes the actual target image, which aims to be as small as possible.
52
+ # Final minimal image with shell for debugging (busybox provides sh)
47
53
FROM busybox:stable-glibc
48
54
49
- # Get the ipfs binary, entrypoint script , and TLS CAs from the build container.
55
+ # Copy ipfs binary, startup scripts , and runtime dependencies
50
56
ENV SRC_DIR=/kubo
51
57
COPY --from=utilities /usr/sbin/gosu /sbin/gosu
52
58
COPY --from=utilities /usr/bin/tini /sbin/tini
53
59
COPY --from=utilities /bin/fusermount /usr/local/bin/fusermount
54
60
COPY --from=utilities /etc/ssl/certs /etc/ssl/certs
55
61
COPY --from=builder $SRC_DIR/cmd/ipfs/ipfs /usr/local/bin/ipfs
56
- COPY --from=builder $SRC_DIR/bin/container_daemon /usr/local/bin/start_ipfs
62
+ COPY --from=builder --chmod=755 $SRC_DIR/bin/container_daemon /usr/local/bin/start_ipfs
57
63
COPY --from=builder $SRC_DIR/bin/container_init_run /usr/local/bin/container_init_run
58
64
59
- # Add suid bit on fusermount so it will run properly
65
+ # Set SUID for fusermount to enable FUSE mounting by non-root user
60
66
RUN chmod 4755 /usr/local/bin/fusermount
61
67
62
- # Fix permissions on start_ipfs (ignore the build machine's permissions)
63
- RUN chmod 0755 /usr/local/bin/start_ipfs
64
-
65
- # Swarm TCP; should be exposed to the public
66
- EXPOSE 4001
67
- # Swarm UDP; should be exposed to the public
68
- EXPOSE 4001/udp
69
- # Daemon API; must not be exposed publicly but to client services under you control
68
+ # Swarm P2P port (TCP/UDP) - expose publicly for peer connections
69
+ EXPOSE 4001 4001/udp
70
+ # API port - keep private, only for trusted clients
70
71
EXPOSE 5001
71
- # Web Gateway; can be exposed publicly with a proxy, e.g. as https://ipfs.example.org
72
+ # Gateway port - can be exposed publicly via reverse proxy
72
73
EXPOSE 8080
73
- # Swarm Websockets; must be exposed publicly when the node is listening using the websocket transport (/ipX/.../tcp/8081/ws).
74
+ # Swarm WebSockets - expose publicly for browser-based peers
74
75
EXPOSE 8081
75
76
76
- # Create the fs-repo directory and switch to a non-privileged user.
77
+ # Create ipfs user (uid 1000) and required directories with proper ownership
77
78
ENV IPFS_PATH=/data/ipfs
78
- RUN mkdir -p $IPFS_PATH \
79
+ RUN mkdir -p $IPFS_PATH /ipfs /ipns /mfs /container-init.d \
79
80
&& adduser -D -h $IPFS_PATH -u 1000 -G users ipfs \
80
- && chown ipfs:users $IPFS_PATH
81
-
82
- # Create mount points for `ipfs mount` command
83
- RUN mkdir /ipfs /ipns /mfs \
84
- && chown ipfs:users /ipfs /ipns /mfs
85
-
86
- # Create the init scripts directory
87
- RUN mkdir /container-init.d \
88
- && chown ipfs:users /container-init.d
81
+ && chown ipfs:users $IPFS_PATH /ipfs /ipns /mfs /container-init.d
89
82
90
- # Expose the fs-repo as a volume.
91
- # start_ipfs initializes an fs-repo if none is mounted.
92
- # Important this happens after the USER directive so permissions are correct.
83
+ # Volume for IPFS repository data persistence
93
84
VOLUME $IPFS_PATH
94
85
95
86
# The default logging level
96
87
ENV GOLOG_LOG_LEVEL=""
97
88
98
- # This just makes sure that:
99
- # 1. There's an fs-repo, and initializes one if there isn't.
100
- # 2. The API and Gateway are accessible from outside the container.
89
+ # Entrypoint initializes IPFS repo if needed and configures networking.
90
+ # tini ensures proper signal handling and zombie process cleanup
101
91
ENTRYPOINT ["/sbin/tini" , "--" , "/usr/local/bin/start_ipfs" ]
102
92
103
- # Healthcheck for the container
104
- # QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn is the CID of empty folder
93
+ # Health check verifies IPFS daemon is responsive.
94
+ # Uses empty directory CID (QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn) as test
105
95
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
106
96
CMD ipfs --api=/ip4/127.0.0.1/tcp/5001 dag stat /ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn || exit 1
107
97
108
- # Execute the daemon subcommand by default
98
+ # Default: run IPFS daemon with auto-migration enabled
109
99
CMD ["daemon" , "--migrate=true" , "--agent-version-suffix=docker" ]
0 commit comments