1
- # Multi-stage build for RustFS production image
2
-
3
- # Build stage: Download and extract RustFS binary
1
+ # -------------------
2
+ # Build stage
3
+ # -------------------
4
4
FROM alpine:3.22 AS build
5
5
6
- # Build arguments for platform and release
7
6
ARG TARGETARCH
8
7
ARG RELEASE=latest
9
8
10
- # Install minimal dependencies for downloading and extracting
11
9
RUN apk add --no-cache ca-certificates curl unzip
12
-
13
- # Create build directory
14
10
WORKDIR /build
15
11
16
- # Set architecture-specific variables
17
- RUN if [ "$TARGETARCH" = "amd64" ]; then \
18
- echo "x86_64-musl" > /tmp/arch; \
19
- elif [ "$TARGETARCH" = "arm64" ]; then \
20
- echo "aarch64-musl" > /tmp/arch; \
12
+ # Download and extract release package matching current TARGETARCH
13
+ # - If RELEASE=latest: take first tag_name from /releases (may include pre-releases)
14
+ # - Otherwise use specified tag (e.g. v0.1.2)
15
+ RUN set -eux; \
16
+ case "$TARGETARCH" in \
17
+ amd64) ARCH_SUBSTR="x86_64-musl" ;; \
18
+ arm64) ARCH_SUBSTR="aarch64-musl" ;; \
19
+ *) echo "Unsupported TARGETARCH=$TARGETARCH" >&2; exit 1 ;; \
20
+ esac; \
21
+ if [ "$RELEASE" = "latest" ]; then \
22
+ TAG="$(curl -fsSL https://api.github.com/repos/rustfs/rustfs/releases \
23
+ | grep -o '" tag_name": " [^"]*" ' | cut -d' "' -f4 | head -n 1)" ; \
21
24
else \
22
- echo "unsupported" > /tmp/arch; \
23
- fi
24
- RUN ARCH=$(cat /tmp/arch) && \
25
- if [ "$ARCH" = "unsupported" ]; then \
26
- echo "Unsupported architecture: $TARGETARCH" && exit 1; \
27
- fi && \
28
- if [ "${RELEASE}" = "latest" ]; then \
29
- # For latest, download from GitHub releases using the -latest suffix
30
- PACKAGE_NAME="rustfs-linux-${ARCH}-latest.zip" ; \
31
- # Use GitHub API to get the latest release URL
32
- LATEST_RELEASE_URL=$(curl -s https://api.github.com/repos/rustfs/rustfs/releases/latest | grep -o '"browser_download_url": "[^"]*' "${PACKAGE_NAME}" '"' | cut -d'"' -f4 | head -1); \
33
- if [ -z "$LATEST_RELEASE_URL" ]; then \
34
- echo "Failed to find latest release for ${PACKAGE_NAME}" >&2; \
35
- exit 1; \
36
- fi; \
37
- DOWNLOAD_URL="$LATEST_RELEASE_URL" ; \
38
- else \
39
- # For specific versions, construct the GitHub release URL directly
40
- # RELEASE is the GitHub release tag (e.g., "1.0.0-alpha.42")
41
- # VERSION is the version in filename (e.g., "v1.0.0-alpha.42")
42
- VERSION="v${RELEASE}" ; \
43
- PACKAGE_NAME="rustfs-linux-${ARCH}-${VERSION}.zip" ; \
44
- DOWNLOAD_URL="https://github.com/rustfs/rustfs/releases/download/${RELEASE}/${PACKAGE_NAME}" ; \
45
- fi && \
46
- echo "Downloading ${PACKAGE_NAME} from ${DOWNLOAD_URL}" >&2 && \
47
- curl -f -L "${DOWNLOAD_URL}" -o rustfs.zip && \
48
- unzip rustfs.zip -d /build && \
49
- chmod +x /build/rustfs && \
50
- rm rustfs.zip || { echo "Failed to download or extract ${PACKAGE_NAME}" >&2; exit 1; }
51
-
52
- # Runtime stage: Configure runtime environment
53
- FROM alpine:3.22.1
25
+ TAG="$RELEASE" ; \
26
+ fi; \
27
+ echo "Using tag: $TAG (arch pattern: $ARCH_SUBSTR)" ; \
28
+ # Find download URL in assets list for this tag that contains arch substring and ends with .zip
29
+ URL="$(curl -fsSL " https://api.github.com/repos/rustfs/rustfs/releases/tags/$TAG" \
30
+ | grep -o " \" browser_download_url\" : \" [^\" ]*${ARCH_SUBSTR}[^\" ]*\\ .zip\" " \
31
+ | cut -d'" ' -f4 | head -n 1)"; \
32
+ if [ -z "$URL" ]; then echo "Failed to locate release asset for $ARCH_SUBSTR at tag $TAG" >&2; exit 1; fi; \
33
+ echo "Downloading: $URL"; \
34
+ curl -fL "$URL" -o rustfs.zip; \
35
+ unzip -q rustfs.zip -d /build; \
36
+ # If binary is not in root directory, try to locate and move from zip to /build/rustfs
37
+ if [ ! -x /build/rustfs ]; then \
38
+ BIN_PATH="$(unzip -Z -1 rustfs.zip | grep -E ' (^|/)rustfs$' | head -n 1 || true)"; \
39
+ if [ -n "$BIN_PATH" ]; then \
40
+ mkdir -p /build/.tmp && unzip -q rustfs.zip "$BIN_PATH" -d /build/.tmp && \
41
+ mv "/build/.tmp/$BIN_PATH" /build/rustfs; \
42
+ fi; \
43
+ fi; \
44
+ [ -x /build/rustfs ] || { echo "rustfs binary not found in asset" >&2; exit 1; }; \
45
+ chmod +x /build/rustfs; \
46
+ rm -rf rustfs.zip /build/.tmp || true
47
+
48
+
49
+ # -------------------
50
+ # Runtime stage
51
+ # -------------------
52
+ FROM alpine:3.22
54
53
55
- # Build arguments and labels
56
54
ARG RELEASE=latest
57
55
ARG BUILD_DATE
58
56
ARG VCS_REF
59
57
60
58
LABEL name="RustFS" \
61
59
vendor="RustFS Team" \
62
60
maintainer="RustFS Team <dev@rustfs.com>" \
63
- version="${RELEASE}" \
61
+ version="v ${RELEASE#v }" \
64
62
release="${RELEASE}" \
65
63
build-date="${BUILD_DATE}" \
66
64
vcs-ref="${VCS_REF}" \
@@ -69,43 +67,37 @@ LABEL name="RustFS" \
69
67
url="https://rustfs.com" \
70
68
license="Apache-2.0"
71
69
72
- # Install runtime dependencies
73
- RUN echo "https://dl-cdn.alpinelinux.org/alpine/v3.20/community" >> /etc/apk/repositories && \
74
- apk update && \
75
- apk add --no-cache ca-certificates bash gosu coreutils shadow && \
70
+ # Install only runtime requirements: certificates and coreutils (provides chroot --userspec)
71
+ RUN apk add --no-cache ca-certificates coreutils && \
76
72
addgroup -g 1000 rustfs && \
77
- adduser -u 1000 -G rustfs -s /bin/bash -D rustfs
73
+ adduser -u 1000 -G rustfs -s /sbin/nologin -D rustfs
78
74
79
- # Copy CA certificates and RustFS binary from build stage
75
+ # Copy binary and entry script (ensure fixed entrypoint.sh exists in repository)
80
76
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
81
77
COPY --from=build /build/rustfs /usr/bin/rustfs
82
-
83
- # Copy entry point script
84
78
COPY entrypoint.sh /entrypoint.sh
85
79
86
- # Set permissions
87
80
RUN chmod +x /usr/bin/rustfs /entrypoint.sh && \
88
81
mkdir -p /data /logs && \
89
82
chown rustfs:rustfs /data /logs && \
90
- chmod 700 /data /logs
91
-
92
- # Environment variables (credentials should be set via environment or secrets)
93
- ENV RUSTFS_ADDRESS=:9000 \
94
- RUSTFS_ACCESS_KEY=rustfsadmin \
95
- RUSTFS_SECRET_KEY=rustfsadmin \
96
- RUSTFS_CONSOLE_ENABLE=true \
97
- RUSTFS_VOLUMES=/data \
98
- RUST_LOG=warn \
99
- RUSTFS_OBS_LOG_DIRECTORY=/logs \
100
- RUSTFS_SINKS_FILE_PATH=/logs
83
+ chmod 0750 /data /logs
84
+
85
+ # Default environment (can be overridden in docker run/compose)
86
+ ENV RUSTFS_ADDRESS=":9000" \
87
+ RUSTFS_ACCESS_KEY="rustfsadmin" \
88
+ RUSTFS_SECRET_KEY="rustfsadmin" \
89
+ RUSTFS_CONSOLE_ENABLE="true" \
90
+ RUSTFS_VOLUMES="/data" \
91
+ RUST_LOG="warn" \
92
+ RUSTFS_OBS_LOG_DIRECTORY="/logs" \
93
+ RUSTFS_SINKS_FILE_PATH="/logs" \
94
+ RUSTFS_USERNAME="rustfs" \
95
+ RUSTFS_GROUPNAME="rustfs" \
96
+ RUSTFS_UID="1000" \
97
+ RUSTFS_GID="1000"
101
98
102
- # Expose port
103
99
EXPOSE 9000
104
-
105
- # Volumes for data and logs
106
100
VOLUME ["/data", "/logs"]
107
101
108
- # Set entry point
109
102
ENTRYPOINT ["/entrypoint.sh"]
110
103
CMD ["/usr/bin/rustfs"]
111
-
0 commit comments