diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 28cf12dafbed28e0de3e67520164b49f2de7ee98..29d423477bd04424c529b0415124babeb8176af2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,6 +2,7 @@ variables:
   BASE_HREF: nshmp
   GITLAB_TOKEN: '${CI_JOB_TOKEN}'
   IMAGE_NAME: ${CODE_REGISTRY_IMAGE}/${CI_PROJECT_NAME}:${ENVIRONMENT}-${CI_COMMIT_SHORT_SHA}
+  NODE_IMAGE: ${CODE_REGISTRY_IMAGE}/${CI_PROJECT_NAME}:${CI_COMMIT_REF_SLUG}--node
   UPSTREAM_PATH: ghsc/nshmp/nshmp-apps
 
 image: ${CI_REGISTRY}/devops/images/usgs/node:lts
@@ -14,6 +15,7 @@ workflow:
 
 stages:
   - init
+  - node-image
   - build
   - image
   - security
@@ -152,6 +154,31 @@ Init:
     - npm ci
   stage: init
 
+####
+# Stage: Node Image
+####
+
+Build Node Image:
+  image: ${CI_REGISTRY}/devops/images/docker:20
+  needs: []
+  script:
+    - |
+      docker build \
+        --build-arg FROM_IMAGE=${CI_REGISTRY}/devops/images/usgs/node:lts \
+        --file ".gitlab/Dockerfile" \
+        --pull \
+        --tag ${NODE_IMAGE} \
+        .
+    - docker push ${NODE_IMAGE}
+  services:
+    - alias: docker
+      name: ${CI_REGISTRY}/devops/images/docker:20-dind
+  stage: node-image
+  tags:
+    - build
+  variables:
+    DOCKER_DRIVER: overlay2
+
 ####
 # Stage: Build
 ####
@@ -160,8 +187,10 @@ Build Project:
   artifacts:
     paths:
       - dist
+  image: ${NODE_IMAGE}
   needs:
     - Init
+    - Build Node Image
   script:
     - npm run build:docker
   stage: build
diff --git a/.gitlab/Dockerfile b/.gitlab/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..b02f452d6a08250157099676092d52b569236e26
--- /dev/null
+++ b/.gitlab/Dockerfile
@@ -0,0 +1,9 @@
+ARG FROM_IMAGE=usgs/node:latest
+
+FROM ${FROM_IMAGE}
+
+USER root
+
+RUN yum install -y git
+
+USER usgs-user