diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
new file mode 100644
index 0000000..f74ee6d
--- /dev/null
+++ b/.github/workflows/docker.yml
@@ -0,0 +1,69 @@
+name: docker-image
+on:
+  workflow_call:
+
+env:
+  REGISTRY: ghcr.io
+  # github.repository as <account>/<repo>
+  IMAGE_NAME: dreamer2368/magudi/magudi_env
+  DOCKERPATH: docker
+
+jobs:
+  docker-ci:
+    runs-on: ubuntu-latest
+    name: "docker env"
+    env:
+      DOCKERPATH: docker
+    steps:
+      - name: test command
+        run: echo "docker-ci command"
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v3
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v3
+      - uses: Ana06/get-changed-files@v2.2.0       
+        id: files
+      - name: DockerPATH configuration
+        run: echo "DOCKERPATH=$DOCKERPATH"
+      - name: DockerPATH - check if files in docker path changed
+        if: contains(steps.files.outputs.all,env.DOCKERPATH) || contains(steps.files.outputs.all,'docker.yml')
+        run: |
+          echo "CI container needs rebuilding..."
+          echo "CI_NEEDS_REBUILD=true" >> $GITHUB_ENV
+      - name: Log into registry ${{ env.REGISTRY }}
+        if: env.CI_NEEDS_REBUILD
+        uses: docker/login-action@v3
+        with:
+          registry: ${{ env.REGISTRY }}
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+      - name: Extract metadata (tags, labels) for Docker
+        id: meta
+        if: env.CI_NEEDS_REBUILD
+        uses: docker/metadata-action@v4
+        with:
+          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+          tags: type=sha
+          flavor: latest=true
+      - name: Build Container motd
+        if: env.CI_NEEDS_REBUILD
+        run: |
+          echo "#!/bin/bash" > ${{env.DOCKERPATH}}/motd.sh
+          echo "echo --------------------------" >> ${{env.DOCKERPATH}}/motd.sh
+          echo "echo magudi_env/CI Development Container"  >> ${{env.DOCKERPATH}}/motd.sh
+          echo "echo \"Revision: `echo ${GITHUB_SHA} | cut -c1-8`\"" >> ${{env.DOCKERPATH}}/motd.sh
+          echo "echo --------------------------" >> ${{env.DOCKERPATH}}/motd.sh
+          chmod 755 ${{env.DOCKERPATH}}/motd.sh
+          cat ${{env.DOCKERPATH}}/motd.sh
+      - name: Docker Image - Build and push
+        if: env.CI_NEEDS_REBUILD
+        uses: docker/build-push-action@v5
+        with:
+          push: true
+          context: ${{ env.DOCKERPATH }}
+          tags: ${{ steps.meta.outputs.tags }}
+          # platforms: linux/amd64,linux/arm64
+          platforms: linux/amd64
\ No newline at end of file
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index ae58a76..36b6824 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -7,10 +7,14 @@ on:
   pull_request:
 
 jobs:
+  docker-image:
+    uses: ./.github/workflows/docker.yml
   magudi-unit:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-latest
+    needs: [docker-image]
     container:
-      image: dreamer2368/magudi_env:latest
+      image: ghcr.io/dreamer2368/magudi/magudi_env:latest
+      # image: dreamer2368/magudi_env:latest
       options: --user 1001 --privileged
     name: CPU-test
     steps:
@@ -34,9 +38,11 @@ jobs:
           cd build
           CTEST_OUTPUT_ON_FAILURE=TRUE make test
   optim-grad-test:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-latest
+    # needs: [docker-image]
     container:
-      image: dreamer2368/magudi_env:latest
+      image: ghcr.io/dreamer2368/magudi/magudi_env:latest
+      # image: dreamer2368/magudi_env:latest
       options: --user 1001 --privileged
     name: Optimization-gradient-test
     steps:
@@ -58,9 +64,11 @@ jobs:
       - name: Multi-point optimization gradient accuracy
         run: bash .github/workflows/optim_grad_test.sh
   optim-test:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-latest
+    # needs: [docker-image]
     container:
-      image: dreamer2368/magudi_env:latest
+      image: ghcr.io/dreamer2368/magudi/magudi_env:latest
+      # image: dreamer2368/magudi_env:latest
       options: --user 1001 --privileged
     name: Optimization-test
     steps:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1a1435..2a4b031 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,8 +52,11 @@ endif()
 execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -show COMMAND awk "{print $1}" OUTPUT_VARIABLE CMAKE_Fortran_COMPILER_PATH)
 execute_process(COMMAND basename ${CMAKE_Fortran_COMPILER_PATH} OUTPUT_VARIABLE CMAKE_Fortran_COMPILER_NAME OUTPUT_STRIP_TRAILING_WHITESPACE)
 
-if(CMAKE_Fortran_COMPILER_NAME STREQUAL "gfortran" OR CMAKE_Fortran_COMPILER_NAME STREQUAL "powerpc64-bgq-linux-gfortran")
-  set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-form -fmodule-private -fimplicit-none -cpp -pedantic-errors -std=f2008")
+if(CMAKE_Fortran_COMPILER_NAME STREQUAL "gfortran" OR CMAKE_Fortran_COMPILER_NAME STREQUAL "powerpc64-bgq-linux-gfortran")  
+  ### For GCC compiler < 10
+  # set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-form -fmodule-private -fimplicit-none -cpp -pedantic-errors -std=f2008")
+  ### For GCC compiler >= 10
+  set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-form -fmodule-private -fimplicit-none -cpp -fallow-argument-mismatch -std=f2008")
   set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -fbacktrace -Wall -Wextra -Waliasing -Wno-unused-dummy-argument -Wno-unused-parameter -ffree-line-length-none -fall-intrinsics -fcheck=all -g")
   set(CMAKE_Fortran_FLAGS_RELEASE "-O3 -ftree-vectorize -ffast-math -funroll-loops")
 elseif(CMAKE_Fortran_COMPILER_NAME STREQUAL "ifort")
@@ -74,7 +77,8 @@ set(CMAKE_Fortran_FORMAT "FREE")
 set(CMAKE_Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/modules)
 
 if(NOT CMAKE_C_COMPILER_ID STREQUAL "XL")
-  set(CMAKE_C_FLAGS_DEBUG "-std=c89 -pedantic-errors")
+  # set(CMAKE_C_FLAGS_DEBUG "-std=c89 -pedantic-errors")
+  set(CMAKE_C_FLAGS_DEBUG "-std=c89")
 endif()
 
 configure_file(${PROJECT_SOURCE_DIR}/include/config.h.in ${PROJECT_BINARY_DIR}/include/config.h)
diff --git a/.github/workflows/Dockerfile b/docker/Dockerfile
similarity index 74%
rename from .github/workflows/Dockerfile
rename to docker/Dockerfile
index 06c8f63..13b38d1 100644
--- a/.github/workflows/Dockerfile
+++ b/docker/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:18.04
+FROM ubuntu:22.04
 
 ENV USERNAME=test
 
@@ -16,19 +16,18 @@ WORKDIR /home/$USERNAME
 RUN sudo apt-get install -yq git
 RUN sudo apt-get install -yq make cmake gcc gfortran libmpich-dev
 RUN sudo apt-get install -yq vim
-RUN sudo apt-get install -yq python python3
-RUN sudo apt-get install -yq python3-pip
-RUN sudo apt-get install -yq curl
-RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
-RUN sudo python2 get-pip.py
+RUN sudo apt-get install -yq python3 python3-pip
+# RUN sudo apt-get install -yq curl
+# RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
+# RUN sudo python2 get-pip.py
 RUN sudo apt-get install -yq git-lfs
 RUN sudo apt-get install -yq valgrind
 RUN sudo apt-get install -yq hdf5-tools
 
 RUN echo "numpy" >> requirements.txt
 RUN echo "scipy" >> requirements.txt
-RUN cp requirements.txt requirements.2.txt
-RUN sudo pip install -r ./requirements.2.txt
+# RUN cp requirements.txt requirements.2.txt
+# RUN sudo pip install -r ./requirements.2.txt
 
 RUN echo "argparse" >> requirements.txt
 RUN echo "tables" >> requirements.txt
diff --git a/test/adjoint_relation/full_rhs.sh b/test/adjoint_relation/full_rhs.sh
index 221508f..8bc4982 100644
--- a/test/adjoint_relation/full_rhs.sh
+++ b/test/adjoint_relation/full_rhs.sh
@@ -7,7 +7,7 @@ exampleDir="AcousticMonopole"
 cp -r ../../examples/${exampleDir} ./
 cp ../../utils/python/plot3dnasa.py ./${exampleDir}
 cd ${exampleDir}
-python2 config.py
+python3 config.py
 mpirun -n 2 $1/full_rhs
 if [ $? -eq 0 ]; then
 	cd ..
diff --git a/test/boundary_operator.f90 b/test/boundary_operator.f90
index 16b5a64..c3cc36c 100644
--- a/test/boundary_operator.f90
+++ b/test/boundary_operator.f90
@@ -222,6 +222,7 @@ program boundary_operator
 
   call A%cleanup()
 
+  call cleanupErrorHandler()
   call MPI_Finalize(ierror)
   if (.not. success) stop -1
   stop 0
diff --git a/test/linearized_relation/full_rhs_linearized.sh b/test/linearized_relation/full_rhs_linearized.sh
index 30e6f0c..57e11bb 100644
--- a/test/linearized_relation/full_rhs_linearized.sh
+++ b/test/linearized_relation/full_rhs_linearized.sh
@@ -7,7 +7,7 @@ exampleDir="AcousticMonopole"
 cp -r ../../examples/${exampleDir} ./
 cp ../../utils/python/plot3dnasa.py ./${exampleDir}
 cd ${exampleDir}
-python2 config.py
+python3 config.py
 mpirun -n 2 $1/full_rhs_linearized
 if [ $? -eq 0 ]; then
 	cd ..
diff --git a/utils/python/plot3dnasa.py b/utils/python/plot3dnasa.py
index 3424ff8..5df64b8 100644
--- a/utils/python/plot3dnasa.py
+++ b/utils/python/plot3dnasa.py
@@ -15,6 +15,14 @@
            'cartesian_grid', 'cubic_bspline_support', 'tanh_support',
            'find_extents']
 
+# scipy.signal.cubic is deprecated after scipy>=1.11.0.
+# equivalent function
+def cubic(x):
+    from scipy.interpolate import BSpline
+    out = BSpline.basis_element([-2, -1, 0, 1, 2])(x)
+    out[(x < -2) | (x > 2)] = 0.0
+    return out
+
 def fdcoeff(stencil, order=1):
     from scipy.linalg import solve
     from scipy.special import gamma
@@ -769,7 +777,7 @@ def cartesian_grid(filename, block_index=0):
     return x, y, z
 
 def cubic_bspline_support(x, x_min, x_max, strict=True):
-    from scipy.signal import cubic
+    # from scipy.signal import cubic
     if x.max() < x_min or x.min() > x_max:
         return np.zeros_like(x)
     if strict: