diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7a6c0f350cee3bd7bffc8279f31cdd8cf3531a7e..635a17af0bd52ca9589a1909038d10bac7e0ba12 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,7 @@
 stages:
   - checks
   - tests
+  - package
   - publish
   - coverage
 
@@ -76,8 +77,29 @@ tests-3.9:
   variables:
     PYTHON_VERSION: "3.9"
 
+.container:
+  stage: package
+  tags: [redshift]
+  services:
+  - docker:dind
+  script:
+    - docker login -u "gitlab-ci-token" -p "$CI_BUILD_TOKEN" $CI_REGISTRY
+    - docker build --pull -t "$CI_REGISTRY_IMAGE:$IMAGE_TAG" .
+    - docker login -u "gitlab-ci-token" -p "$CI_BUILD_TOKEN" $CI_REGISTRY
+    - docker tag "$CI_REGISTRY_IMAGE:$IMAGE_TAG" "$CI_REGISTRY_IMAGE:$IMAGE_TAG"
+    - docker push "$CI_REGISTRY_IMAGE:$IMAGE_TAG"
+    - docker tag "$CI_REGISTRY_IMAGE:$IMAGE_TAG" "$CI_REGISTRY_IMAGE:latest"
+    - docker push "$CI_REGISTRY_IMAGE:latest"
+
+container:
+  extends: .container
+  variables:
+    IMAGE_TAG: "dev"
+  rules:
+    - when: manual
+
 pypi_test:
-  stage: publish
+  stage: package
   rules:
     - if: $CI_COMMIT_TAG
       when: manual
@@ -86,7 +108,7 @@ pypi_test:
     - poetry publish --build --username $PYPI_TEST_LOGIN --password $PYPI_TEST_PASSWORD --repository pypi_test
 
 pypi:
-  stage: publish
+  stage: package
   rules:
     - if: $CI_COMMIT_TAG
       when: manual
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..744ef940da379e808eacc7442dd19f00f5c387e1
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,12 @@
+FROM registry.duniter.org/docker/python3/poetry/3.9:latest
+
+# Install Silkaj
+RUN cd silkaj && poetry install
+
+# Set up alias to directly get silkaj command
+# https://stackoverflow.com/a/3638886
+RUN printf '#!/bin/bash\npoetry run silkaj "$@"' > /usr/bin/silkaj && \
+    chmod +x /usr/bin/silkaj
+
+WORKDIR /silkaj
+CMD ["/usr/bin/silkaj"]