diff --git a/.dockerignore b/.dockerignore
index c602282b36ad815e0557014b233db6fd42a54137..1c3094162ad40ba10af706c6346be54a3d053eec 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -6,3 +6,4 @@ docker/Dockerfile
 docker-compose.yml
 arm-build/
 **/target/
+build/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 950da1fb61b12ec2a47e9b1f4977b740700dc1f8..4077c4ea0f08c777e4148969735d9bd7c12d774c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,3 +1,6 @@
+# Runner tags:
+# - podman: use 'podman' to build multiplatform images
+
 stages:
   - schedule
   - labels
@@ -40,7 +43,7 @@ check_labels:
 .env:
   image: paritytech/ci-linux:1.68.2-buster
   tags:
-    - dind
+    - podman
 
 fmt_and_clippy:
   extends: .env
@@ -58,95 +61,63 @@ fmt_and_clippy:
     - cargo clippy -- -V
     - cargo clippy --all --tests -- -D warnings
 
-build_debug:
-  extends: .env
-  rules:
-    - if: $CI_COMMIT_TAG
-      when: never
-    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "master"'
-      changes:
-      - Cargo.lock
-    - when: never
+.docker_build:
   stage: build
   script:
-    - cargo clean -p duniter
-    - cargo build --locked
-    - mkdir build
-    - mv target/debug/duniter build/duniter
-  artifacts:
-    paths:
-      - build/
-    expire_in: 3 day
-  cache:
-    - key:
-        files:
-          - Cargo.lock
-      paths:
-        - target/debug
-      policy: push
+    - echo podman build --layers --tag "$IMAGE_NAME:$IMAGE_TAG" -f docker/Dockerfile $PODMAN_BUILD_OPTIONS .
+    - podman build --layers --tag "$IMAGE_NAME:$IMAGE_TAG" -f docker/Dockerfile $PODMAN_BUILD_OPTIONS .
+  tags:
+    - podman
 
-build_debug_with_cache:
-  extends: .env
+.docker_deploy:
+  stage: deploy
+  before_script:
+    - podman login -u "duniterteam" -p "$DUNITERTEAM_PASSWD" docker.io
+  tags:
+    - podman
+
+.docker_deploy_native:
+  extends: .docker_deploy
+  script:
+    - podman push "localhost/$IMAGE_NAME:$IMAGE_TAG" "docker://docker.io/$IMAGE_NAME:$IMAGE_TAG"
+
+.docker_deploy_multiplatform:
+  extends: .docker_deploy
+  script:
+    - podman manifest rm "$MANIFEST" 2>/dev/null || true
+    - podman build --layers --platform linux/amd64,linux/arm64 --manifest "$MANIFEST" -f docker/Dockerfile $PODMAN_BUILD_OPTIONS .
+    - podman manifest push --all "$MANIFEST" "docker://docker.io/$IMAGE_NAME:$IMAGE_TAG"
+  after_script:
+    - podman manifest rm "$MANIFEST"
+  variables:
+    MANIFEST: "localhost/manifest-$IMAGE_NAME:$IMAGE_TAG"
+
+build_debug:
+  extends: .docker_build
   rules:
-    - changes:
-      - Cargo.lock
-      when: never
     - if: $CI_COMMIT_TAG
       when: never
     - if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "master"'
     - when: never
-  stage: build
-  script:
-    - cargo clean -p duniter
-    - cargo build --locked
-    - mkdir build
-    - mv target/debug/duniter build/duniter
-  artifacts:
-    paths:
-      - build/
-    expire_in: 3 day
-  cache:
-    - key:
-        files:
-          - Cargo.lock
-      paths:
-        - target/debug
-      policy: pull
+  variables:
+    IMAGE_NAME: "duniter/duniter-v2s"
+    IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
+    PODMAN_BUILD_OPTIONS: "--build-arg debug=1"
 
 build_release:
-  extends: .env
+  extends: .docker_build
   rules:
     - if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
-    - when: never
-  stage: build
-  script:
-    - cargo build --locked --release
-    - mkdir build
-    - mv target/release/duniter build/duniter
-  artifacts:
-    paths:
-      - build/
-    expire_in: 3 day
-
-build_release_manual:
-  extends: .env
-  rules:
-    - if: $CI_COMMIT_TAG
-      when: never
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "master"'
     - when: manual
-  stage: build
-  allow_failure: true
-  script:
-    - cargo build --locked --release
-    - mkdir build
-    - mv target/release/duniter build/duniter
-  artifacts:
-    paths:
-      - build/
-    expire_in: 3 day
+  variables:
+    IMAGE_NAME: "duniter/duniter-v2s"
+    IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
+    PODMAN_BUILD_OPTIONS: "--platform linux/amd64"
 
-tests_debug:
-  extends: .env
+test_debug:
+  stage: tests
+  extends: .docker_build
   rules:
     - if: $CI_COMMIT_REF_NAME =~ /^wip*$/
       when: manual
@@ -154,128 +125,83 @@ tests_debug:
       when: never
     - if: '$CI_MERGE_REQUEST_ID || $CI_COMMIT_BRANCH == "master"'
     - when: manual
-  stage: tests
   variables:
-    DUNITER_BINARY_PATH: "../build/duniter"
-    DUNITER_END2END_TESTS_SPAWN_NODE_TIMEOUT: "20"
-  script:
-    - cargo test --workspace --exclude duniter-end2end-tests --exclude duniter-live-tests
-    - cargo cucumber -i account_creation*
-    - cargo cucumber -i certification*
-    - cargo cucumber -i identity_creation*
-    - cargo cucumber -i monetary_mass*
-    - cargo cucumber -i oneshot_account*
-    - cargo cucumber -i transfer_all*
-  after_script:
-    - cd target/debug/deps/
-    - rm cucumber_tests-*.d
-    - mv cucumber_tests* ../../../build/duniter-cucumber
-  artifacts:
-    paths:
-      - build/
-    expire_in: 3 day
+    IMAGE_NAME: "duniter/duniter-v2s-test"
+    IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
+    PODMAN_BUILD_OPTIONS: "--target build --build-arg debug=1 --build-arg cucumber=1"
 
-tests_release:
-  extends: .env
+test_release:
+  stage: tests
+  extends: .docker_build
   rules:
     - if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
     - when: never
-  stage: tests
   variables:
-    DUNITER_BINARY_PATH: "../build/duniter"
-    DUNITER_END2END_TESTS_SPAWN_NODE_TIMEOUT: "20"
-  script:
-    - cargo test --workspace --exclude duniter-end2end-tests --exclude duniter-live-tests
-    - cargo cucumber -i account_creation*
-    - cargo cucumber -i certification*
-    - cargo cucumber -i identity_creation*
-    - cargo cucumber -i monetary_mass*
-    - cargo cucumber -i oneshot_account*
-    - cargo cucumber -i transfer_all*
-  after_script:
-    - cd target/debug/deps/
-    - rm cucumber_tests-*.d
-    - mv cucumber_tests* ../../../build/duniter-cucumber
-  artifacts:
-    paths:
-      - build/
-    expire_in: 3 day
-  dependencies:
-    - build_release
+    IMAGE_NAME: "duniter/duniter-v2s-test"
+    IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
+    PODMAN_BUILD_OPTIONS: "--target build --build-arg cucumber=1"
 
-.docker-build-app-image:
+deploy_docker_debug_sha:
   stage: deploy
-  image: docker:18.06
-  tags:
-    - docker
-  services:
-    - docker:dind
-  before_script:
-    - docker info
-  script:
-    - docker pull $CI_REGISTRY_IMAGE:$IMAGE_TAG || true
-    - docker build --cache-from $CI_REGISTRY_IMAGE:$IMAGE_TAG --pull -t "$CI_REGISTRY_IMAGE:$IMAGE_TAG" -f $DOCKERFILE_PATH .
-    - docker login -u "duniterteam" -p "$DUNITERTEAM_PASSWD"
-    - docker tag "$CI_REGISTRY_IMAGE:$IMAGE_TAG" "duniter/duniter-v2s:$IMAGE_TAG"
-    - docker push "duniter/duniter-v2s:$IMAGE_TAG"
-
-deploy_docker_test_image:
-  extends: .docker-build-app-image
+  extends: .docker_deploy_native
   rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^wip*$/
-      when: manual
-    - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH == "master"'
+    - if: $CI_COMMIT_TAG
       when: never
-    - when: manual
-  allow_failure: true
+    - if: $CI_COMMIT_BRANCH == "master"
   variables:
-    DOCKERFILE_PATH: "docker/Dockerfile"
-    IMAGE_TAG: "test-image-$CI_COMMIT_SHORT_SHA"
+    IMAGE_NAME: "duniter/duniter-v2s"
+    IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
 
-deploy_docker_debug_sha:
-  extends: .docker-build-app-image
+deploy_docker_release_sha:
+  stage: deploy
+  extends: .docker_deploy_native
   rules:
     - if: $CI_COMMIT_TAG
       when: never
-    - if: $CI_COMMIT_BRANCH == "master"
+    - when: manual
   variables:
-    DOCKERFILE_PATH: "docker/Dockerfile"
-    IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
-  after_script:
-    - docker login -u "duniterteam" -p "$DUNITERTEAM_PASSWD"
-    - docker tag "duniter/duniter-v2s:$IMAGE_TAG" "duniter/duniter-v2s:debug-latest"
-    - docker push "duniter/duniter-v2s:debug-latest"
+    IMAGE_NAME: "duniter/duniter-v2s"
+    IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
 
-deploy_docker_release_sha:
-  extends: .docker-build-app-image
+deploy_docker_release_sha_multiplatform:
+  stage: deploy
+  needs: ["deploy_docker_release_sha"]
+  extends: .docker_deploy_multiplatform
   rules:
     - if: $CI_COMMIT_TAG
       when: never
     - when: manual
-  allow_failure: true
   variables:
-    DOCKERFILE_PATH: "docker/Dockerfile"
+    IMAGE_NAME: "duniter/duniter-v2s"
     IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
-  dependencies:
-    - build_release_manual
 
 deploy_docker_release_tag:
-  extends: .docker-build-app-image
+  stage: deploy
+  extends: .docker_deploy_native
   rules:
     - if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
     - when: never
   variables:
-    DOCKERFILE_PATH: "docker/Dockerfile"
+    IMAGE_NAME: "duniter/duniter-v2s"
+    IMAGE_TAG: "$CI_COMMIT_TAG"
+
+deploy_docker_release_tag_multiplatform:
+  stage: deploy
+  needs: ["deploy_docker_release_tag"]
+  extends: .docker_deploy_multiplatform
+  rules:
+    - if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
+    - when: never
+  script:
+    - !reference [.docker_deploy_multiplatform, script]
+    - podman manifest push --all "$MANIFEST" "docker://docker.io/$IMAGE_NAME:latest"
+  variables:
+    IMAGE_NAME: "duniter/duniter-v2s"
     IMAGE_TAG: "$CI_COMMIT_TAG"
-  after_script:
-    - docker login -u "duniterteam" -p "$DUNITERTEAM_PASSWD"
-    - docker tag "duniter/duniter-v2s:$IMAGE_TAG" "duniter/duniter-v2s:latest"
-    - docker push "duniter/duniter-v2s:latest"
-  dependencies:
-    - build_release
 
 readme_docker_release_tag:
   stage: deploy_readme
+  needs: ["deploy_docker_release_tag"]
   rules:
     - if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
     - when: never
@@ -283,7 +209,7 @@ readme_docker_release_tag:
     name: chko/docker-pushrm
     entrypoint: ["/bin/sh", "-c", "/docker-pushrm"]
   variables:
-    DOCKER_USER: "duniterteam"
+    DOCKER_USER: duniterteam
     DOCKER_PASS: "$DUNITERTEAM_PASSWD"
     PUSHRM_SHORT: "Duniter v2 based on Substrate framework"
     PUSHRM_TARGET: "docker.io/duniter/duniter-v2s"
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 84b1b6af06f650998800272e371464a24034efe2..7b3e0dd7c8196ffe11311176956bddc61b04d186 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -1,44 +1,76 @@
+# Workaround for https://github.com/containers/buildah/issues/4742
+FROM debian:bullseye-slim as target
+
 # ------------------------------------------------------------------------------
 # Build Stage
 # ------------------------------------------------------------------------------
 
-# Building for Debian buster because we need the binary to be compatible
-# with the image paritytech/ci-linux:production (currently based on
-# debian:buster-slim) used by the gitlab CI
-FROM rust:1-buster as build
+# When building for a foreign arch, use cross-compilation
+# https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/
+FROM --platform=$BUILDPLATFORM rust:1-bullseye as build
+ARG BUILDPLATFORM
+ARG TARGETPLATFORM
+
+# We need the target arch triplet in both Debian and rust flavor
+RUN echo "DEBIAN_ARCH_TRIPLET='$(dpkg-architecture -A${TARGETPLATFORM#linux/} -qDEB_TARGET_MULTIARCH)'" >>/root/dynenv
+RUN . /root/dynenv && \
+    echo "RUST_ARCH_TRIPLET='$(echo "$DEBIAN_ARCH_TRIPLET" | sed -E 's/-linux-/-unknown&/')'" >>/root/dynenv
+
 WORKDIR /root
 
 # Copy source tree
 COPY . .
 
-RUN test -x build/duniter || \
-    ( \
-        apt-get update && \
-        DEBIAN_FRONTEND=noninteractive apt-get install -y clang cmake protobuf-compiler \
-    )
+RUN apt-get update && \
+    DEBIAN_FRONTEND=noninteractive apt-get install -y clang cmake protobuf-compiler
 
 # build duniter
-ARG threads=1
-RUN test -x build/duniter || \
-    ( \
-        cargo build --release -j $threads && \
-        mkdir -p build && \
-        mv target/release/duniter build/ \
-    )
-
-# Create fake duniter-cucumber if is not exist
-# The goal is to avoid error later, this binary is optional
-RUN test -x build/duniter-cucumber || \
-    ( \
-        mkdir -p build && \
-        touch build/duniter-cucumber \
-    )
+ARG debug=0
+RUN if [ "$debug" = 0 ]; then \
+        echo "CARGO_OPTIONS=--release" >>/root/dynenv && \
+        echo "TARGET_FOLDER=release" >>/root/dynenv; \
+    else \
+        echo "TARGET_FOLDER=debug" >>/root/dynenv; \
+    fi
+
+# Configure cross-build environment if need be
+RUN set -x && \
+    if [ "$TARGETPLATFORM" != "$BUILDPLATFORM" ]; then \
+        . /root/dynenv && \
+        apt install -y gcc-$DEBIAN_ARCH_TRIPLET binutils-$DEBIAN_ARCH_TRIPLET && \
+        rustup target add "$RUST_ARCH_TRIPLET" && \
+        : https://github.com/rust-lang/cargo/issues/4133 && \
+        echo "RUSTFLAGS='-C linker=$DEBIAN_ARCH_TRIPLET-gcc'; export RUSTFLAGS" >>/root/dynenv; \
+    fi
+
+# Build
+RUN set -x && \
+    cat /root/dynenv && \
+    . /root/dynenv && \
+    cargo build --locked $CARGO_OPTIONS --target "$RUST_ARCH_TRIPLET" && \
+    mkdir -p build && \
+    mv target/$RUST_ARCH_TRIPLET/$TARGET_FOLDER/duniter build/
+
+# Run tests if requested, expted when cross-building
+ARG cucumber=0
+RUN if [ "$cucumber" != 0 ] && [ "$TARGETPLATFORM" = "$BUILDPLATFORM" ]; then \
+        cargo test --workspace --exclude duniter-end2end-tests --exclude duniter-live-tests && \
+        cargo cucumber -i account_creation* && \
+        cargo cucumber -i certification* && \
+        cargo cucumber -i identity_creation* && \
+        cargo cucumber -i monetary_mass* && \
+        cargo cucumber -i oneshot_account* && \
+        cargo cucumber -i transfer_all* && \
+        cd target/debug/deps/ && \
+        rm cucumber_tests-*.d && \
+        mv cucumber_tests* ../../../build/duniter-cucumber; \
+    fi
 
 # ------------------------------------------------------------------------------
 # Final Stage
 # ------------------------------------------------------------------------------
 
-FROM debian:buster-slim
+FROM target
 
 LABEL maintainer="Gilles Filippini <gilles.filippini@pini.fr>"
 LABEL version="0.0.0"
@@ -54,6 +86,5 @@ ENTRYPOINT ["docker-entrypoint"]
 USER duniter
 
 # Intall
-COPY --from=build /root/build/duniter /usr/local/bin/duniter
-COPY --from=build /root/build/duniter-cucumber /usr/local/bin/duniter-cucumber
+COPY --from=build /root/build /usr/local/bin/
 COPY docker/docker-entrypoint /usr/local/bin/