| 1 | # syntax=docker/dockerfile:1 |
| 2 | # Enables BuildKit with cache mounts for faster builds |
| 3 | |
| 4 | # GO_VERSION is the source of truth for the Go toolchain version. CI parses |
| 5 | # the `go` directive from go.mod and overrides this build arg, so the |
| 6 | # published image always matches the version `setup-go` installs from go.mod. |
| 7 | # The default below is what `docker build .` (without --build-arg) uses, and |
| 8 | # `.github/workflows/docker-check.yml` lints that this default stays in sync |
| 9 | # with go.mod. When bumping Go, update both go.mod and this default together. |
| 10 | ARG GO_VERSION=1.26.2 |
| 11 | FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:${GO_VERSION} AS builder |
| 12 | |
| 13 | ARG TARGETOS TARGETARCH |
| 14 | |
| 15 | ENV SRC_DIR=/kubo |
| 16 | |
| 17 | # Cache go module downloads between builds for faster rebuilds |
| 18 | COPY go.mod go.sum $SRC_DIR/ |
| 19 | WORKDIR $SRC_DIR |
| 20 | RUN --mount=type=cache,target=/go/pkg/mod \ |
| 21 | go mod download |
| 22 | |
| 23 | COPY . $SRC_DIR |
| 24 | |
| 25 | # Preload an in-tree but disabled-by-default plugin by adding it to the IPFS_PLUGINS variable |
| 26 | # e.g. docker build --build-arg IPFS_PLUGINS="foo bar baz" |
| 27 | ARG IPFS_PLUGINS |
| 28 | |
| 29 | # Allow for other targets to be built, e.g.: docker build --build-arg MAKE_TARGET="nofuse" |
| 30 | ARG MAKE_TARGET=build |
| 31 | |
| 32 | # Build ipfs binary with cached go modules and build cache. |
| 33 | # mkdir .git/objects allows git rev-parse to read commit hash for version info |
| 34 | RUN --mount=type=cache,target=/go/pkg/mod \ |
| 35 | --mount=type=cache,target=/root/.cache/go-build \ |
| 36 | mkdir -p .git/objects \ |
| 37 | && GOOS=$TARGETOS GOARCH=$TARGETARCH GOFLAGS=-buildvcs=false make ${MAKE_TARGET} IPFS_PLUGINS=$IPFS_PLUGINS |
| 38 | |
| 39 | # Extract required runtime tools from Debian. |
| 40 | # We use Debian instead of Alpine because we need glibc compatibility |
| 41 | # for the busybox base image we're using. |
| 42 | FROM debian:bookworm-slim AS utilities |
| 43 | RUN set -eux; \ |
| 44 | apt-get update; \ |
| 45 | apt-get install -y --no-install-recommends \ |
| 46 | tini \ |
| 47 | # Using gosu (~2MB) instead of su-exec (~20KB) because it's easier to |
| 48 | # install on Debian. Useful links: |
| 49 | # - https://github.com/ncopa/su-exec#why-reinvent-gosu |
| 50 | # - https://github.com/tianon/gosu/issues/52#issuecomment-441946745 |
| 51 | gosu \ |
| 52 | # fusermount enables IPFS mount commands |
| 53 | fuse \ |
| 54 | ca-certificates \ |
| 55 | ; \ |
| 56 | apt-get clean; \ |
| 57 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* |
| 58 | |
| 59 | # Final minimal image with shell for debugging (busybox provides sh) |
| 60 | FROM busybox:stable-glibc |
| 61 | |
| 62 | # Copy ipfs binary, startup scripts, and runtime dependencies |
| 63 | ENV SRC_DIR=/kubo |
| 64 | COPY --from=utilities /usr/sbin/gosu /sbin/gosu |
| 65 | COPY --from=utilities /usr/bin/tini /sbin/tini |
| 66 | COPY --from=utilities /bin/fusermount /usr/local/bin/fusermount |
| 67 | COPY --from=utilities /etc/ssl/certs /etc/ssl/certs |
| 68 | COPY --from=builder $SRC_DIR/cmd/ipfs/ipfs /usr/local/bin/ipfs |
| 69 | COPY --from=builder --chmod=755 $SRC_DIR/bin/container_daemon /usr/local/bin/start_ipfs |
| 70 | COPY --from=builder $SRC_DIR/bin/container_init_run /usr/local/bin/container_init_run |
| 71 | |
| 72 | # Set SUID for fusermount to enable FUSE mounting by non-root user |
| 73 | RUN chmod 4755 /usr/local/bin/fusermount |
| 74 | |
| 75 | # Swarm P2P port (TCP/UDP) - expose publicly for peer connections |
| 76 | EXPOSE 4001 4001/udp |
| 77 | # API port - keep private, only for trusted clients |
| 78 | EXPOSE 5001 |
| 79 | # Gateway port - can be exposed publicly via reverse proxy |
| 80 | EXPOSE 8080 |
| 81 | # Swarm WebSockets - expose publicly for browser-based peers |
| 82 | EXPOSE 8081 |
| 83 | |
| 84 | # Create ipfs user (uid 1000) and required directories with proper ownership |
| 85 | ENV IPFS_PATH=/data/ipfs |
| 86 | RUN mkdir -p $IPFS_PATH /ipfs /ipns /mfs /container-init.d \ |
| 87 | && adduser -D -h $IPFS_PATH -u 1000 -G users ipfs \ |
| 88 | && chown ipfs:users $IPFS_PATH /ipfs /ipns /mfs /container-init.d |
| 89 | |
| 90 | # Volume for IPFS repository data persistence |
| 91 | VOLUME $IPFS_PATH |
| 92 | |
| 93 | # The default logging level |
| 94 | ENV GOLOG_LOG_LEVEL="" |
| 95 | |
| 96 | # Entrypoint initializes IPFS repo if needed and configures networking. |
| 97 | # tini ensures proper signal handling and zombie process cleanup |
| 98 | ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/start_ipfs"] |
| 99 | |
| 100 | # Health check via "ipfs diag healthy": verifies RPC + DAG pipeline, and |
| 101 | # fails after SIGINT/SIGTERM to catch half-shutdown states. |
| 102 | HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ |
| 103 | CMD ipfs --api=/ip4/127.0.0.1/tcp/5001 diag healthy > /dev/null 2>&1 || exit 1 |
| 104 | |
| 105 | # Default: run IPFS daemon with auto-migration enabled |
| 106 | CMD ["daemon", "--migrate=true", "--agent-version-suffix=docker"] |