diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a5892bb8c467c04767cbb0caa86b8d1632848a29..15aa602ffd577fae754498a7b1afbc354aa82e47 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -93,6 +93,25 @@ image: $CI_REGISTRY/packaging/apkg/ci/debian-10-full:apkg
     reports:
       junit: report.xml
 
+.nixos: &nixos
+  tags:
+    - docker
+    - linux
+    - amd64
+  image: nixos/nix
+  variables:
+    #NIX_PATH: nixpkgs=https://github.com/nixos/nixpkgs/archive/nixos-unstable.tar.gz
+    NIX_PATH: nixpkgs=https://github.com/vcunat/nixpkgs/archive/p/apkg.tar.gz
+  before_script:
+    - nix-env -f '<nixpkgs>' -iA gitMinimal
+    - *setup-git
+    # The image auto-detects as alpine distro, and tests don't allow overriding easily :-/
+    - echo 'ID=nixos' > /etc/os-release
+    # Some archive scripts need /bin/bash
+    - nix build nixpkgs.bash && ln -s "$(realpath ./result/bin/bash)" /bin/bash
+    # Use bootstrap apkg to install itself from the current commit
+    - nix-shell '<nixpkgs>' -p apkg --run 'apkg install'
+
 
 # basic tests
 
@@ -149,6 +168,7 @@ debian-10-apkg:
   image: $CI_REGISTRY/packaging/apkg/ci/debian-10:apkg
   <<: *apkg
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_apkg.py --junitxml=report.xml
 
@@ -156,6 +176,7 @@ ubuntu-18.04-apkg:
   image: $CI_REGISTRY/packaging/apkg/ci/ubuntu-18.04:apkg
   <<: *apkg
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_apkg.py --junitxml=report.xml
 
@@ -163,6 +184,7 @@ ubuntu-20.04-apkg:
   image: $CI_REGISTRY/packaging/apkg/ci/ubuntu-20.04:apkg
   <<: *apkg
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_apkg.py --junitxml=report.xml
 
@@ -187,25 +209,6 @@ suse-15-apkg:
     - *setup-project
     - py.test3 -v ci/tests/test_apkg.py --junitxml=report.xml
 
-.nixos: &nixos
-  tags:
-    - docker
-    - linux
-    - amd64
-  image: nixos/nix
-  variables:
-    #NIX_PATH: nixpkgs=https://github.com/nixos/nixpkgs/archive/nixos-unstable.tar.gz
-    NIX_PATH: nixpkgs=https://github.com/vcunat/nixpkgs/archive/p/apkg.tar.gz
-  before_script:
-    - nix-env -f '<nixpkgs>' -iA gitMinimal
-    - *setup-git
-    # The image auto-detects as alpine distro, and tests don't allow overriding easily :-/
-    - echo 'ID=nixos' > /etc/os-release
-    # Some archive scripts need /bin/bash
-    - nix build nixpkgs.bash && ln -s "$(realpath ./result/bin/bash)" /bin/bash
-    # Use bootstrap apkg to install itself from the current commit
-    - nix-shell '<nixpkgs>' -p apkg --run 'apkg install'
-
 nixos-unstable-apkg:
   <<: *apkg
   <<: *nixos
@@ -244,6 +247,7 @@ debian-10-bird:
   image: $CI_REGISTRY/packaging/apkg/ci/debian-10:apkg
   <<: *bird
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_bird.py --junitxml=report.xml
 
@@ -251,6 +255,7 @@ ubuntu-18.04-bird:
   image: $CI_REGISTRY/packaging/apkg/ci/ubuntu-18.04:apkg
   <<: *bird
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_bird.py --junitxml=report.xml
 
@@ -258,6 +263,7 @@ ubuntu-20.04-bird:
   image: $CI_REGISTRY/packaging/apkg/ci/ubuntu-20.04:apkg
   <<: *bird
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_bird.py --junitxml=report.xml
 
@@ -310,6 +316,7 @@ debian-10-libyang:
   image: $CI_REGISTRY/packaging/apkg/ci/debian-10:apkg
   <<: *libyang
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_libyang.py --junitxml=report.xml
 
@@ -317,6 +324,7 @@ ubuntu-18.04-libyang:
   image: $CI_REGISTRY/packaging/apkg/ci/ubuntu-18.04:apkg
   <<: *libyang
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_libyang.py --junitxml=report.xml
 
@@ -324,6 +332,7 @@ ubuntu-20.04-libyang:
   image: $CI_REGISTRY/packaging/apkg/ci/ubuntu-20.04:apkg
   <<: *libyang
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_libyang.py --junitxml=report.xml
 
@@ -376,6 +385,7 @@ debian-10-knot-dns:
   image: $CI_REGISTRY/packaging/apkg/ci/debian-10:apkg
   <<: *knot-dns
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_knot_dns.py --junitxml=report.xml
 
@@ -383,6 +393,7 @@ ubuntu-18.04-knot-dns:
   image: $CI_REGISTRY/packaging/apkg/ci/ubuntu-18.04:apkg
   <<: *knot-dns
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_knot_dns.py --junitxml=report.xml
 
@@ -390,6 +401,7 @@ ubuntu-20.04-knot-dns:
   image: $CI_REGISTRY/packaging/apkg/ci/ubuntu-20.04:apkg
   <<: *knot-dns
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_knot_dns.py --junitxml=report.xml
 
@@ -450,6 +462,7 @@ debian-10-knot-resolver:
   image: $CI_REGISTRY/packaging/apkg/ci/debian-10:apkg
   <<: *knot-resolver
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_knot_resolver.py --junitxml=report.xml
 
@@ -457,6 +470,7 @@ ubuntu-20.04-knot-resolver:
   image: $CI_REGISTRY/packaging/apkg/ci/ubuntu-20.04:apkg
   <<: *knot-resolver
   script:
+    - apt update
     - *setup-project
     - py.test-3 -v ci/tests/test_knot_resolver.py --junitxml=report.xml
 
diff --git a/ci/images/README.md b/ci/images/README.md
index 9a72209953e95a65aaa944f2c456acf3e4be0ee1..90b9314dda7aeed681e3183a54923a09e5a6f97f 100644
--- a/ci/images/README.md
+++ b/ci/images/README.md
@@ -8,16 +8,25 @@ use `build.sh` to build docker image, for example:
 ./build.sh debian-10
 ```
 
-## upload image into apkg CI
+## push (upload) image into apkg CI
 
-you need to login first:
+you need to **login** first:
 
 ```
 $ docker login registry.nic.cz
 ```
 
-then you can use `upload.sh` script:
+then you can use `push.sh` script:
 
 ```
-./upload.sh debian-10
+./push.sh debian-10
+```
+
+## build & push images
+
+use `update.sh` wrapper to build and push multiple images
+using `build.sh` and `push.sh` scripts described above:
+
+```
+./update.sh debian-10 debian-11 rocky-8
 ```
diff --git a/ci/images/debian-10-full/Dockerfile b/ci/images/debian-10-full/Dockerfile
index b2284a54c3dcfdeebe2e5a256abddfc2ad6265c2..1acf6855cbe7b5bd5ee8312055056efd1005162f 100644
--- a/ci/images/debian-10-full/Dockerfile
+++ b/ci/images/debian-10-full/Dockerfile
@@ -32,7 +32,7 @@ RUN pip3 install \
     pylint
 # basic deps
 RUN apt-get install -y -qqq \
-    python3-beautifulsoup4 \
+    python3-bs4 \
     python3-blessings \
     python3-click \
     python3-cached-property \
diff --git a/ci/images/debian-10/Dockerfile b/ci/images/debian-10/Dockerfile
index a312273bbf49fc336a7f7b4409c20f5c4c337857..a90d26afcb65915be9b9b1a853155d43e2c5a676 100644
--- a/ci/images/debian-10/Dockerfile
+++ b/ci/images/debian-10/Dockerfile
@@ -34,7 +34,7 @@ RUN apt-get install -y -qqq \
     python3-pytest-sugar
 # basic deps
 RUN apt-get install -y -qqq \
-    python3-beautifulsoup4 \
+    python3-bs4 \
     python3-blessings \
     python3-click \
     python3-jinja2 \
diff --git a/ci/images/upload.sh b/ci/images/push.sh
similarity index 100%
rename from ci/images/upload.sh
rename to ci/images/push.sh
diff --git a/ci/images/update.sh b/ci/images/update.sh
new file mode 100755
index 0000000000000000000000000000000000000000..1db2441acf1e1db8b82a5804e16ab530d219eebb
--- /dev/null
+++ b/ci/images/update.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# build and upload docker image(s) into apkg registry
+#
+# this is a simple wrapper around build.sh and update.sh
+
+if [[ $# -le 0 ]]; then
+    echo "usage: $0 IMAGE..."
+    exit 1
+fi
+set -e
+
+for IMAGE in "$@"
+do
+    echo "Building $IMAGE..."
+    ./build.sh $IMAGE
+    echo "Pushing $IMAGE..."
+    ./push.sh $IMAGE
+done
+