Skip to content

Commit 4ee4bb1

Browse files
committed
feat(core): use shared box image for project containers
1 parent 45f4f3d commit 4ee4bb1

3 files changed

Lines changed: 63 additions & 14 deletions

File tree

packages/app/src/lib/core/templates/dockerfile.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,22 @@ import { renderDockerfilePrompt } from "../templates-prompt.js"
33
import { renderDockerfileGlab } from "./glab.js"
44
import { renderDockerfileGitleaks, renderDockerfileOpenCode } from "./tools.js"
55

6+
// CHANGE: use the shared link-foundation box as the generated project base image
7+
// WHY: issue #267 asks docker-git to reuse unified box containers instead of maintaining a raw Ubuntu workspace base
8+
// QUOTE(ТЗ): "Что бы не зависить только от своих обновлений, а иметь единую инфраструктру есть смысл юзать готовый репозиторий"
9+
// REF: issue-267
10+
// SOURCE: https://github.com/link-foundation/box
11+
// FORMAT THEOREM: renderDockerfile(config) -> base_image(rendered) = DOCKER_GIT_BASE_IMAGE
12+
// PURITY: CORE
13+
// INVARIANT: the rendered Dockerfile inherits language/runtime tooling from link-foundation/box while preserving docker-git bootstrap layers
14+
// COMPLEXITY: O(1)/O(1)
15+
const dockerGitBaseImage = "ghcr.io/link-foundation/box:latest"
16+
617
const renderDockerfilePrelude = (): string =>
7-
`FROM ubuntu:24.04
18+
`ARG DOCKER_GIT_BASE_IMAGE=${dockerGitBaseImage}
19+
FROM \${DOCKER_GIT_BASE_IMAGE}
820
21+
USER root
922
ARG UBUNTU_APT_MIRROR=
1023
ENV DEBIAN_FRONTEND=noninteractive
1124
ENV NVM_DIR=/usr/local/nvm
@@ -187,13 +200,16 @@ const renderDockerfileBun = (config: TemplateConfig): string =>
187200

188201
const renderDockerfileUsers = (config: TemplateConfig): string =>
189202
`# Create non-root user for SSH (align UID/GID with host user 1000)
190-
RUN if id -u ubuntu >/dev/null 2>&1; then \
191-
if getent group 1000 >/dev/null 2>&1; then \
192-
EXISTING_GROUP="$(getent group 1000 | cut -d: -f1)"; \
193-
if [ "$EXISTING_GROUP" != "${config.sshUser}" ]; then groupmod -n ${config.sshUser} "$EXISTING_GROUP" || true; fi; \
203+
RUN for BASE_USER in box ubuntu; do \
204+
if [ "$BASE_USER" != "${config.sshUser}" ] && id -u "$BASE_USER" >/dev/null 2>&1; then \
205+
if getent group 1000 >/dev/null 2>&1; then \
206+
EXISTING_GROUP="$(getent group 1000 | cut -d: -f1)"; \
207+
if [ "$EXISTING_GROUP" != "${config.sshUser}" ]; then groupmod -n ${config.sshUser} "$EXISTING_GROUP" || true; fi; \
208+
fi; \
209+
usermod -l ${config.sshUser} -d /home/${config.sshUser} -m -s /usr/bin/zsh "$BASE_USER" || true; \
210+
break; \
194211
fi; \
195-
usermod -l ${config.sshUser} -d /home/${config.sshUser} -m -s /usr/bin/zsh ubuntu || true; \
196-
fi
212+
done
197213
RUN if id -u ${config.sshUser} >/dev/null 2>&1; then \
198214
usermod -u 1000 -g 1000 -o ${config.sshUser}; \
199215
else \

packages/lib/src/core/templates/dockerfile.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,22 @@ import { renderDockerfilePrompt } from "../templates-prompt.js"
33
import { renderDockerfileGlab } from "./glab.js"
44
import { renderDockerfileGitleaks, renderDockerfileOpenCode } from "./tools.js"
55

6+
// CHANGE: use the shared link-foundation box as the generated project base image
7+
// WHY: issue #267 asks docker-git to reuse unified box containers instead of maintaining a raw Ubuntu workspace base
8+
// QUOTE(ТЗ): "Что бы не зависить только от своих обновлений, а иметь единую инфраструктру есть смысл юзать готовый репозиторий"
9+
// REF: issue-267
10+
// SOURCE: https://github.com/link-foundation/box
11+
// FORMAT THEOREM: renderDockerfile(config) -> base_image(rendered) = DOCKER_GIT_BASE_IMAGE
12+
// PURITY: CORE
13+
// INVARIANT: the rendered Dockerfile inherits language/runtime tooling from link-foundation/box while preserving docker-git bootstrap layers
14+
// COMPLEXITY: O(1)/O(1)
15+
const dockerGitBaseImage = "ghcr.io/link-foundation/box:latest"
16+
617
const renderDockerfilePrelude = (): string =>
7-
`FROM ubuntu:24.04
18+
`ARG DOCKER_GIT_BASE_IMAGE=${dockerGitBaseImage}
19+
FROM \${DOCKER_GIT_BASE_IMAGE}
820
21+
USER root
922
ARG UBUNTU_APT_MIRROR=
1023
ENV DEBIAN_FRONTEND=noninteractive
1124
ENV NVM_DIR=/usr/local/nvm
@@ -187,13 +200,16 @@ const renderDockerfileBun = (config: TemplateConfig): string =>
187200

188201
const renderDockerfileUsers = (config: TemplateConfig): string =>
189202
`# Create non-root user for SSH (align UID/GID with host user 1000)
190-
RUN if id -u ubuntu >/dev/null 2>&1; then \
191-
if getent group 1000 >/dev/null 2>&1; then \
192-
EXISTING_GROUP="$(getent group 1000 | cut -d: -f1)"; \
193-
if [ "$EXISTING_GROUP" != "${config.sshUser}" ]; then groupmod -n ${config.sshUser} "$EXISTING_GROUP" || true; fi; \
203+
RUN for BASE_USER in box ubuntu; do \
204+
if [ "$BASE_USER" != "${config.sshUser}" ] && id -u "$BASE_USER" >/dev/null 2>&1; then \
205+
if getent group 1000 >/dev/null 2>&1; then \
206+
EXISTING_GROUP="$(getent group 1000 | cut -d: -f1)"; \
207+
if [ "$EXISTING_GROUP" != "${config.sshUser}" ]; then groupmod -n ${config.sshUser} "$EXISTING_GROUP" || true; fi; \
208+
fi; \
209+
usermod -l ${config.sshUser} -d /home/${config.sshUser} -m -s /usr/bin/zsh "$BASE_USER" || true; \
210+
break; \
194211
fi; \
195-
usermod -l ${config.sshUser} -d /home/${config.sshUser} -m -s /usr/bin/zsh ubuntu || true; \
196-
fi
212+
done
197213
RUN if id -u ${config.sshUser} >/dev/null 2>&1; then \
198214
usermod -u 1000 -g 1000 -o ${config.sshUser}; \
199215
else \

packages/lib/tests/core/templates.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ describe("renderEntrypointDnsRepair", () => {
5454
})
5555

5656
describe("renderDockerfile", () => {
57+
it("uses the shared box image as the project container base", () => {
58+
const dockerfile = renderDockerfile(makeTemplateConfig())
59+
60+
expect(dockerfile).toContain("ARG DOCKER_GIT_BASE_IMAGE=ghcr.io/link-foundation/box:latest")
61+
expect(dockerfile).toContain("FROM ${DOCKER_GIT_BASE_IMAGE}")
62+
expect(dockerfile).toContain("USER root")
63+
expect(dockerfile).not.toContain("FROM ubuntu:24.04")
64+
})
65+
66+
it("renames the box base user to the configured SSH user", () => {
67+
const dockerfile = renderDockerfile(makeTemplateConfig())
68+
69+
expect(dockerfile).toContain("for BASE_USER in box ubuntu; do")
70+
expect(dockerfile).toContain('if [ "$BASE_USER" != "dev" ] && id -u "$BASE_USER" >/dev/null 2>&1; then')
71+
expect(dockerfile).toContain('usermod -l dev -d /home/dev -m -s /usr/bin/zsh "$BASE_USER" || true')
72+
})
73+
5774
it("installs session sync from npmjs with a local fallback", () => {
5875
const dockerfile = renderDockerfile(makeTemplateConfig())
5976

0 commit comments

Comments
 (0)