-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathdockerfile
More file actions
160 lines (113 loc) · 5.51 KB
/
dockerfile
File metadata and controls
160 lines (113 loc) · 5.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
FROM alpine AS base
ARG USER=magg
ARG HOME=/home/${USER}
ARG PACKAGE=${USER}
ARG UID=1000
ENV PATH="${HOME}/.local/bin:${PATH}"
RUN apk add --no-cache tini bash curl nano nodejs npm && \
addgroup -g ${UID} -S ${USER} && \
adduser -u ${UID} -S -G ${USER} -h ${HOME} -s /bin/bash ${USER} && \
chmod 755 ${HOME}
USER ${USER}
WORKDIR ${HOME}
FROM base AS venv
ARG PYTHON_VERSION
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
UV_COMPILE_BYTECODE=0 \
UV_LINK_MODE=copy \
PATH="${HOME}/.venv/bin:${PATH}" \
VIRTUAL_ENV="${HOME}/.venv" \
PS1="(${PACKAGE}) \h:\w\$ "
# Activating the venv through bash the "normal" way:
# ENV BASH_ENV="${HOME}/.bashrc" # enables .bashrc to be sourced in non-interactive shells e.g. `bash -c`
# RUN echo "source ~/.venv/bin/activate" >> ${HOME}/.bashrc
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ADD --chown=${USER}:${USER} .python-version ./
RUN if [ -n "${PYTHON_VERSION}" ]; then \
echo "${PYTHON_VERSION}" > .python-version; \
fi
FROM venv AS proj
LABEL org.opencontainers.image.source=https://github.com/sitbon/magg \
org.opencontainers.image.description="Magg - The Model Context Protocol (MCP) Aggregator (Project)" \
org.opencontainers.image.licenses=AGPLv3 \
org.opencontainers.image.authors="Phillip Sitbon <phillip.sitbon@gmail.com>"
ARG MAGG_CONFIG_PATH="${HOME}/.magg/config.json"
ARG MAGG_READ_ONLY=false
ENV MAGG_CONFIG_PATH="${MAGG_CONFIG_PATH}" \
MAGG_READ_ONLY="${MAGG_READ_ONLY}"
RUN --mount=type=cache,uid=${UID},gid=${UID},target=${HOME}/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --no-install-project --no-dev
# Fix for Python 3.12 extension suffix mismatch on Alpine
# Python 3.12 expects linux-gnu but we have linux-musl wheels
RUN if [ "${PYTHON_VERSION}" = "3.12" ]; then \
find .venv/lib -name "*.cpython-*-x86_64-linux-musl.so" -exec sh -c \
'ln -sf "$(basename "$1")" "$(dirname "$1")/$(echo "$(basename "$1")" | sed "s/-musl\.so$/-gnu.so/")"' _ {} \; ; \
fi
ADD --chown=${USER}:${USER} pyproject.toml uv.lock readme.md license.md ./
ADD --chown=${USER}:${USER} ${PACKAGE}/ ./${PACKAGE}/
RUN --mount=type=cache,uid=${UID},gid=${UID},target=${HOME}/.cache/uv \
uv sync --locked --no-dev
RUN mkdir -p .magg && \
chmod 755 .magg
EXPOSE 8000
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["magg", "serve", "--http", "--host", "0.0.0.0", "--port", "8000"]
FROM proj AS pre
LABEL org.opencontainers.image.source=https://github.com/sitbon/magg \
org.opencontainers.image.description="Magg - The Model Context Protocol (MCP) Aggregator (Staging)" \
org.opencontainers.image.licenses=AGPLv3 \
org.opencontainers.image.authors="Phillip Sitbon <phillip.sitbon@gmail.com>"
ENV MAGG_LOG_LEVEL=INFO
USER root
RUN chown -R root:${USER} ${HOME}/.venv ${HOME}/${PACKAGE} && \
chmod -R a-w,a+rX ${HOME}/.venv ${HOME}/${PACKAGE} && \
chown -R ${USER}:${USER} ${HOME}/.magg && \
chmod -R u+rwX ${HOME}/.magg && \
if [ "${MAGG_READ_ONLY}" = "true" ] || [ "${MAGG_READ_ONLY}" = "1" ] || [ "${MAGG_READ_ONLY}" = "yes" ]; then \
chmod -R a-w ${HOME}/.magg; \
fi
# Note: The above check does not work with volume mounts (e.g. compose), so the real enforcement
# is done in the application code.
USER ${USER}
FROM pre AS pro
LABEL org.opencontainers.image.source=https://github.com/sitbon/magg \
org.opencontainers.image.description="Magg - The Model Context Protocol (MCP) Aggregator" \
org.opencontainers.image.licenses=AGPLv3 \
org.opencontainers.image.authors="Phillip Sitbon <phillip.sitbon@gmail.com>"
ENV MAGG_LOG_LEVEL=WARNING
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD ["magg", "status"]
FROM proj AS dev
LABEL org.opencontainers.image.source=https://github.com/sitbon/magg \
org.opencontainers.image.description="Magg - The Model Context Protocol (MCP) Aggregator (Development)" \
org.opencontainers.image.licenses=AGPLv3 \
org.opencontainers.image.authors="Phillip Sitbon <phillip.sitbon@gmail.com>"
ENV MAGG_LOG_LEVEL=DEBUG
ADD --chown=${USER}:${USER} test/ ./test/
RUN --mount=type=cache,uid=1000,gid=1000,target=${HOME}/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --dev
FROM dev AS pkg
LABEL org.opencontainers.image.source=https://github.com/sitbon/magg \
org.opencontainers.image.description="Magg - The Model Context Protocol (MCP) Aggregator (Packaging)" \
org.opencontainers.image.licenses=AGPLv3 \
org.opencontainers.image.authors="Phillip Sitbon <phillip.sitbon@gmail.com>"
RUN --mount=type=cache,uid=${UID},gid=${UID},target=${HOME}/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv build
FROM venv AS user
LABEL org.opencontainers.image.source=https://github.com/sitbon/magg \
org.opencontainers.image.description="Magg - The Model Context Protocol (MCP) Aggregator (User Environment)" \
org.opencontainers.image.licenses=AGPLv3 \
org.opencontainers.image.authors="Phillip Sitbon <phillip.sitbon@gmail.com>"
ENV PS1="(user) \h:\w\$ "
COPY --from=pkg ${HOME}/dist/ ${HOME}/dist/
RUN uv init --no-workspace --no-package --no-readme --no-description --name user && \
uv sync && \
uv add "magg[dev] @ $(ls -t1 dist/*.whl | head -n 1)"
CMD ["bash"]