Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion engine/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
FROM busybox:1.36.1 AS data-dirs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor

Pin the new BusyBox stage to an immutable digest.

The busybox:1.36.1 tag is mutable; pin the reference to a sha256 digest to ensure build reproducibility and prevent supply-chain risks where the image content changes without a code change.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@engine/Dockerfile` at line 1, The BusyBox base image used in the data-dirs
stage is still referenced by a mutable tag, so update the FROM instruction in
the data-dirs stage to use an immutable sha256 digest instead of busybox:1.36.1.
Keep the stage name and overall Dockerfile structure the same, and replace the
tag with the pinned digest so builds remain reproducible.


RUN mkdir -p /app/data /data && chown -R 65532:65532 /app/data /data

FROM gcr.io/distroless/cc-debian12:nonroot

ARG TARGETARCH
COPY iii-${TARGETARCH} /app/iii
COPY --from=data-dirs --chown=65532:65532 /app/data /app/data
COPY --from=data-dirs --chown=65532:65532 /data /data

ENV III_EXECUTION_CONTEXT=docker
ENV III_ENV=development

EXPOSE 49134 3111 3112 9464
EXPOSE 49134 3111 3112
ENTRYPOINT ["/app/iii"]
CMD ["--config", "/app/config.yaml"]

Expand Down
2 changes: 1 addition & 1 deletion engine/tests/fixtures/templates/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ COPY config.yaml /app/config.yaml
# generated one yet, and `iiidev/iii:latest` is distroless so `RUN touch`
# isn't an option.)

EXPOSE 49134 3111 3112 9464
EXPOSE 49134 3111 3112
ENTRYPOINT ["/app/iii"]
CMD ["--config", "/app/config.yaml"]
5 changes: 3 additions & 2 deletions engine/tests/fixtures/templates/docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ services:
- "49134:49134" # WebSocket (worker connections)
- "3111:3111" # REST API
- "3112:3112" # Stream API
- "9464:9464" # Prometheus metrics
volumes:
- ./config.yaml:/app/config.yaml:ro
- iii_data:/app/data
environment:
- RUST_LOG=info
- III_EXECUTION_CONTEXT=docker
Expand Down Expand Up @@ -38,6 +38,7 @@ services:
# - rabbitmq_data:/var/lib/rabbitmq
# restart: unless-stopped

# volumes:
volumes:
iii_data:
# redis_data:
# rabbitmq_data:
14 changes: 14 additions & 0 deletions engine/tests/project_init_e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ fn fixtures() -> PathBuf {
.join("templates")
}

fn assert_compose_mounts_engine_data_volume(project: &Path) {
let compose = std::fs::read_to_string(project.join("docker-compose.yml")).unwrap();
assert!(
compose.contains("- iii_data:/app/data"),
"docker-compose.yml should mount writable engine data, got:\n{compose}"
);
assert!(
compose.contains("volumes:\n iii_data:"),
"docker-compose.yml should declare the iii_data named volume, got:\n{compose}"
);
}

#[test]
fn project_init_creates_minimum_scaffold() {
let dir = tempdir().unwrap();
Expand Down Expand Up @@ -164,6 +176,7 @@ fn project_init_with_docker_flag_writes_docker_assets_with_device_id() {
assert!(dir.path().join("Dockerfile").exists());
assert!(dir.path().join("docker-compose.yml").exists());
assert!(dir.path().join(".env").exists());
assert_compose_mounts_engine_data_volume(dir.path());

let ini = std::fs::read_to_string(dir.path().join(".iii").join("project.ini")).unwrap();
let device_id_in_ini = ini
Expand Down Expand Up @@ -217,6 +230,7 @@ fn project_generate_docker_uses_existing_project_ini_device_id() {
dockerfile.contains("ENV III_HOST_USER_ID=preseeded-xyz"),
"Dockerfile should bake the existing device_id, got:\n{dockerfile}"
);
assert_compose_mounts_engine_data_volume(dir.path());

let env = std::fs::read_to_string(dir.path().join(".env")).unwrap();
assert!(
Expand Down
Loading