-
Notifications
You must be signed in to change notification settings - Fork 8
Description
Summary
Please add support for more of Docker Compose's build: options during coast build, especially:
build.target
Right now, the implementation appears to intentionally preserve only context and dockerfile when building host-side images for compose services.
I would be willing to implement this if the maintainers think it fits the project direction.
Why this matters
For dev workflows, it is not uncommon to use a Dockerfile with:
- a lightweight dev stage selected via
build.target - a later production-only stage that should not run in normal local builds
Plain docker compose build handles this correctly. coast build currently does not.
That makes Coast harder to adopt for projects that already have a clean multi-stage Compose-based dev/prod setup.
Example
Compose service:
services:
backend:
build:
context: .
dockerfile: Dockerfile
target: compose-devDockerfile shape:
FROM python:3.13-slim AS builder
# ...
FROM runtime-base AS compose-dev
FROM debian:bookworm-slim AS asset-fetch
ARG ASSET_REF=mainDesired behavior:
coast buildshould honortarget: compose-dev
Current implementation
The current implementation explicitly ignores target, args, and similar build: fields.
- ComposeBuildDirective only stores context and dockerfile
coasts/coast-docker/src/compose_build.rs
Lines 14 to 23 in d1e4493
pub struct ComposeBuildDirective { /// The compose service name (e.g., "app"). pub service_name: String, /// Build context path, relative to the compose file directory. pub context: String, /// Optional Dockerfile path (relative to context). pub dockerfile: Option<String>, /// The coast-built image tag (e.g., "coast-built/my-project/app:latest"). pub coast_image_tag: String, } - parse_compose_file_inner(...) only extracts context and dockerfile
coasts/coast-docker/src/compose_build.rs
Lines 129 to 153 in d1e4493
if has_build { let build_val = value.get("build").unwrap(); let (context, dockerfile) = match build_val { serde_yaml::Value::String(s) => (s.clone(), None), serde_yaml::Value::Mapping(m) => { let ctx = m .get(serde_yaml::Value::String("context".to_string())) .and_then(|v| v.as_str()) .unwrap_or(".") .to_string(); let df = m .get(serde_yaml::Value::String("dockerfile".to_string())) .and_then(|v| v.as_str()) .map(std::string::ToString::to_string); (ctx, df) } _ => (".".to_string(), None), }; build_directives.push(ComposeBuildDirective { service_name: service_name.clone(), context, dockerfile, coast_image_tag: coast_built_image_tag(project, &service_name), }); - docker_build_cmd(...) emits docker build without --target
coasts/coast-docker/src/compose_build.rs
Lines 293 to 317 in d1e4493
/// Construct the `docker build` command for a build directive. /// /// Returns the command as a vector of strings suitable for `tokio::process::Command`. pub fn docker_build_cmd(directive: &ComposeBuildDirective, compose_dir: &Path) -> Vec<String> { let mut cmd = vec![ "docker".to_string(), "build".to_string(), "-t".to_string(), directive.coast_image_tag.clone(), ]; if let Some(ref df) = directive.dockerfile { cmd.push("-f".to_string()); cmd.push( compose_dir .join(&directive.context) .join(df) .display() .to_string(), ); } cmd.push(compose_dir.join(&directive.context).display().to_string()); cmd - Test comment explicitly stating that args, target, etc. are ignored
coasts/coast-docker/src/compose_build.rs
Lines 684 to 700 in d1e4493
#[test] fn test_parse_build_with_extra_fields() { // build: can have args, target, etc. — we only care about context and dockerfile let yaml = r#" services: app: build: context: . dockerfile: Dockerfile args: NODE_ENV: production target: builder "#; let result = parse_compose_file(yaml, "proj").unwrap(); assert_eq!(result.build_directives.len(), 1); assert_eq!(result.build_directives[0].context, "."); assert_eq!(
Implementation note
I recognize there are other build arguments that would be valuable to have, such as --build-arg. There's a Rust compose_spec crate that might be useful for processing arguments more generically. Though I'm not sure it would be preferred over picking out fields individually. Limiting the scope today probably makes it easier to debug usage issues.
Requested capability
- Support compose
build.targetby passing it through todocker build --target. - Consider supporting other useful compose build fields as well, or document the intentionally supported subset clearly.
Environment
- Coasts: 0.1.24
- macOS
- Docker Desktop