Skip to content

Commit

Permalink
Fix image build errors with Podman and NerdCTL.
Browse files Browse the repository at this point in the history
Ensures that Docker and NerdCTL, which support the custom `--output` and `--cache-from` flags use them, while Podman and unknown container engines use the strict, minimal subset Podman supports. This is because Podman only supports a registry/repository, without a tag, for `--cache-from`, which means it synchronizes poorly with our target subs, like `centos`. Therefore, unless unsupported, we should always use the features available for our container engine.

This also fixes the `--pull` flag on NerdCTL, which is unsupported. Engines without BuildKit extensions by default, such as NerdCTL, now do not use `buildx` unless explicitly enabled with `CROSS_CONTAINER_ENGINE_NO_BUILDKIT=0`.
  • Loading branch information
Alexhuszagh committed Sep 30, 2022
1 parent 5261b6a commit 3a960e4
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changes/1033.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"description": "fix --cache-from using podman.",
"type": "fixed",
"issues": [1031]
}
41 changes: 40 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,45 @@ jobs:
run: ./ci/test-docker-in-docker.sh
shell: bash

podman:
name: podman
runs-on: ubuntu-latest
needs: [shellcheck, test, check]
if: github.event_name == 'push'
strategy:
fail-fast: false
outputs:
has-image: ${{ steps.prepare-meta.outputs.has-image }}
images: ${{ steps.build-docker-image.outputs.images && fromJSON(steps.build-docker-image.outputs.images) }}
coverage-artifact: ${{ steps.cov.outputs.artifact-name }}
steps:
- uses: actions/checkout@v3

- uses: ./.github/actions/setup-rust

- name: Install Podman
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo apt-get update
sudo apt-get install podman --no-install-recommends --assume-yes
- name: LLVM instrument coverage
id: cov
uses: ./.github/actions/cargo-llvm-cov
with:
name: cross-podman-aarch64-unknown-linux-gnu

- name: Install cross
run: cargo install --path . --force --debug

- name: Run Podman Test
run: ./ci/test-podman.sh
env:
CROSS_CONTAINER_ENGINE: podman
TARGET: aarch64-unknown-linux-gnu
shell: bash

publish:
needs: [build, check, fmt, clippy, cargo-deny]
runs-on: ubuntu-latest
Expand All @@ -331,7 +370,7 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}

conclusion:
needs: [shellcheck, fmt, clippy, test, generate-matrix, build, publish, check, remote, bisect, docker-in-docker, foreign]
needs: [shellcheck, fmt, clippy, test, generate-matrix, build, publish, check, remote, bisect, docker-in-docker, foreign, podman]
if: always()
runs-on: ubuntu-latest
steps:
Expand Down
41 changes: 41 additions & 0 deletions ci/test-podman.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
# shellcheck disable=SC1091,SC1090

# test to see that running and building images with podman works.

set -x
set -eo pipefail

export CROSS_CONTAINER_ENGINE=podman
if [[ -z "${TARGET}" ]]; then
export TARGET="aarch64-unknown-linux-gnu"
fi

ci_dir=$(dirname "${BASH_SOURCE[0]}")
ci_dir=$(realpath "${ci_dir}")
. "${ci_dir}"/shared.sh

main() {
local td=
local parent=
local target="${TARGET}"

retry cargo fetch
cargo build
export CROSS="${PROJECT_HOME}/target/debug/cross"

td="$(mkcargotemp -d)"
parent=$(dirname "${td}")
pushd "${td}"
cargo init --bin --name "hello" .

echo '[build]
pre-build = ["apt-get update"]' > "${parent}/Cross.toml"

CROSS_CONTAINER_ENGINE="${CROSS_ENGINE}" "${CROSS}" build --target "${target}" --verbose

popd
rm -rf "${td}"
}

main
2 changes: 1 addition & 1 deletion src/docker/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl<'a> Dockerfile<'a> {
) -> Result<String> {
let uses_zig = options.cargo_variant.uses_zig();
let mut docker_build = docker::command(&options.engine);
match docker::Engine::has_buildkit() {
match options.engine.has_buildkit() {
true => docker_build.args(["buildx", "build"]),
false => docker_build.arg("build"),
};
Expand Down
30 changes: 28 additions & 2 deletions src/docker/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum EngineType {
Docker,
Podman,
PodmanRemote,
Nerdctl,
Other,
}

Expand All @@ -32,6 +33,29 @@ impl EngineType {
pub fn is_docker(&self) -> bool {
matches!(self, Self::Docker)
}

/// Returns `true` if the engine build supports the `--output` flag.
#[must_use]
pub fn supports_output_flag(&self) -> bool {
!matches!(self, Self::Other)
}

/// Returns `true` if the engine build supports the `--pull` flag.
#[must_use]
pub fn supports_pull_flag(&self) -> bool {
!matches!(self, Self::Nerdctl | Self::Other)
}

/// Returns `true` if the engine build supports the `--cache-from type=` key.
///
/// Some container engines, especially podman, do not support the `type`
/// key of `--cache-from` during the image build steps. They also do
/// not support any tags for the `--cache-from` steps either. See:
/// https://docs.podman.io/en/latest/markdown/podman-build.1.html#cache-from
#[must_use]
pub fn supports_cache_from_type(&self) -> bool {
matches!(self, Self::Docker | Self::Nerdctl)
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -110,10 +134,10 @@ impl Engine {
}

#[must_use]
pub fn has_buildkit() -> bool {
pub fn has_buildkit(&self) -> bool {
!env::var("CROSS_CONTAINER_ENGINE_NO_BUILDKIT")
.map(|x| bool_from_envvar(&x))
.unwrap_or_default()
.unwrap_or(self.kind == EngineType::Nerdctl)
}
}

Expand All @@ -132,6 +156,8 @@ fn get_engine_info(
EngineType::PodmanRemote
} else if stdout_help.contains("podman") {
EngineType::Podman
} else if stdout_help.contains("nerdctl") {
EngineType::Nerdctl
} else if stdout_help.contains("docker") && !stdout_help.contains("emulate") {
EngineType::Docker
} else {
Expand Down
12 changes: 8 additions & 4 deletions xtask/src/build_docker_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ pub fn build_docker_image(
msg_info.note(format_args!("Build {target} for {}", platform.target))?;
}
let mut docker_build = docker::command(engine);
let has_buildkit = docker::Engine::has_buildkit();
let has_buildkit = engine.has_buildkit();
match has_buildkit {
true => docker_build.args(["buildx", "build"]),
false => docker_build.arg("build"),
Expand All @@ -187,7 +187,7 @@ pub fn build_docker_image(

if push {
docker_build.arg("--push");
} else if engine.kind.is_docker() && no_output {
} else if engine.kind.supports_output_flag() && no_output {
docker_build.args(["--output", "type=tar,dest=/dev/null"]);
} else if has_buildkit {
docker_build.arg("--load");
Expand Down Expand Up @@ -216,17 +216,21 @@ pub fn build_docker_image(
tags = vec![target.image_name(&repository, tag)];
}

docker_build.arg("--pull");
if engine.kind.supports_pull_flag() {
docker_build.arg("--pull");
}
if no_cache {
docker_build.arg("--no-cache");
} else {
} else if engine.kind.supports_cache_from_type() {
docker_build.args([
"--cache-from",
&format!(
"type=registry,ref={}",
target.image_name(&repository, "main")
),
]);
} else {
docker_build.args(["--cache-from", &format!("{repository}/{}", target.name)]);
}

if push {
Expand Down

0 comments on commit 3a960e4

Please sign in to comment.