|
|
@@ -128,12 +128,17 @@ pub async fn serve(
|
|
|
use self::sync::sync_image_to_nodes;
|
|
|
|
|
|
// Build image on specified node if needed.
|
|
|
+ // `built_on` records the node that actually (re)built the image. After a
|
|
|
+ // fresh build that image is authoritative — the sync step below must pull
|
|
|
+ // FROM it, never let a peer's older image (by creation timestamp) overwrite
|
|
|
+ // the new build.
|
|
|
+ let mut built_on: Option<String> = None;
|
|
|
if let Some(ref build_node_name) = opts.build_node {
|
|
|
if !opts.dry_run && !cluster.nodes.iter().any(|n| n.name == *build_node_name) {
|
|
|
anyhow::bail!("build-node '{}' not in cluster", build_node_name);
|
|
|
}
|
|
|
if !opts.dry_run {
|
|
|
- crate::docker::build::handle_build(
|
|
|
+ let did_build = crate::docker::build::handle_build(
|
|
|
config,
|
|
|
&cluster,
|
|
|
recipe_name,
|
|
|
@@ -142,6 +147,9 @@ pub async fn serve(
|
|
|
build_node_name,
|
|
|
)
|
|
|
.await?;
|
|
|
+ if did_build {
|
|
|
+ built_on = Some(build_node_name.clone());
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -168,13 +176,14 @@ pub async fn serve(
|
|
|
let should_sync =
|
|
|
opts.sync_image && recipe.sync_image && !opts.dry_run && cluster.nodes.len() > 1;
|
|
|
if should_sync {
|
|
|
- sync_image_to_nodes(
|
|
|
- config,
|
|
|
- &cluster,
|
|
|
- &recipe.docker_image,
|
|
|
- opts.sync_image_source.as_deref(),
|
|
|
- )
|
|
|
- .await?;
|
|
|
+ // After a fresh build the build node holds the authoritative image:
|
|
|
+ // force it as the sync source so a peer's older image (by creation
|
|
|
+ // timestamp, or from a no-op `docker load` round-trip) can't overwrite
|
|
|
+ // the new build. The "most recently created" heuristic only applies
|
|
|
+ // when nothing was built here and no explicit --sync-image-source was
|
|
|
+ // given — i.e. the nodes merely disagree and we pick the newest.
|
|
|
+ let sync_source = built_on.as_deref().or(opts.sync_image_source.as_deref());
|
|
|
+ sync_image_to_nodes(config, &cluster, &recipe.docker_image, sync_source).await?;
|
|
|
}
|
|
|
|
|
|
// Drop page cache on all nodes right before starting containers.
|