I am utilizing CircleCI and ECR orb to build my docker image and push it to Elastic Container Registry ( ECR ) but I keep running into the following error: ERROR: failed to solve: failed to compute cache key: "/init.sh" not found
.
My directory structure is as follows:
Terraform
.circleci
infra
frontend
--- Dockerfile
--- init.sh
So basically I have a Terraform directory. Inside that directory I have an infra
directory and a frontend
directory. The frontend directory consists of my Dockerfile
and my init.sh
script.
The contents of my Dockerfile is as follows:
FROM node:14
ENV JQ_VERSION=1.6
RUN wget --no-check-certificate https://github.com/stedolan/jq/releases/download/jq-${JQ_VERSION}/jq-linux64 -O /tmp/jq-linux64
RUN cp /tmp/jq-linux64 /usr/bin/jq
RUN chmod +x /usr/bin/jq
WORKDIR /app
COPY . .
RUN jq 'to_entries | map_values({ (.key) : ("$" + .key) }) | reduce .[] as $item ({}; . + $item)' ./src/config.json > ./src/config.tmp.json && mv ./src/config.tmp.json ./src/config.json
RUN npm install && npm run build
FROM nginx:1.17
ENV JSFOLDER=/usr/share/nginx/html/js/*.js
COPY ./init.sh /usr/bin/init.sh
RUN chmod +x /usr/bin/init.sh
WORKDIR /usr/share/nginx/html
COPY --from=0 /app/dist .
ENTRYPOINT [ "init.sh" ]
and my CircleCI config has the following content:
version: '2.1'
orbs:
aws-ecr: circleci/aws-ecr@8.2.1
aws-cli: circleci/aws-cli@3.1
jobs:
build:
machine:
image: ubuntu-2004:2022.10.1
steps:
- checkout
- aws-ecr/build-and-push-image:
repo: frontend
push-image: true
region: ${AWS_REGION}
registry-id: REGISTRY_ID
dockerfile: frontend/Dockerfile
path: .
tag: ${CIRCLE_SHA1}
workflows:
test:
jobs:
- build:
But CircleCI gives me the following error:
> [stage-1 2/5] COPY ./init.sh /usr/bin/init.sh:
------
ERROR: failed to solve: failed to compute cache key: "/init.sh" not found: not found
Exited with code exit status 1
It requires reading and understanding of the error message (and yes a little bit of discipline if it is all-new as we're easily distracted in complex computer systems):
> ERROR: failed to solve: failed to compute cache key: "/init.sh" not found: not found
The message result is at the end, the operation in front, separator is :
. Additionally the message is prefixed by its class (ERROR
).
More structural:
If you're coming from development, compare it a bit with a backtrace, but you need to throw a bit more brain on it as we don't have file paths and line numbers (not even binary offsets) here.
For me for example, it is that 2. and 3. tell me "not found" is a file not found. As this is within Dockerfile (or Docker build) context, we can spot one operation already, as we know it involves files and a real file-system that could give such I/O errors:
COPY ./init.sh /usr/bin/init.sh
Then I'd read-up the manual for COPY
1 to understand a bit better why the message tells it is /init.sh
(absolute path) while within the COPY
directive it is ./init.sh
(relative path). I may not understand it within three minutes therefore I skip with this knowledge and know that I only assume it is a match.
Then given it is a match I look into its CircleCI binding:
- aws-ecr/build-and-push-image:
repo: frontend
push-image: true
region: ${AWS_REGION}
registry-id: REGISTRY_ID
dockerfile: frontend/Dockerfile
path: .
tag: ${CIRCLE_SHA1}
Again, we need to get into the know and that is finding the reference for the CircleCI Orb and its command in question: aws-ecr/build-and-push-image
2. Without it, we have no reference and aren't able to gather any meaning (just to guess it, but who needs brute force all the time? The strong weak!).
As our first assumption is this is file-system related we can perhaps identify the dockerfile
and path
:
dockerfile
: Name of dockerfile to use. Defaults to Dockerfile.REQUIRED: No DEFAULT: Dockerfile TYPE: string
path
: Path to the directory containing your Dockerfile. Defaults to . (working directory).REQUIRED: No DEFAULT: . TYPE: string
You then lay all those three piece of information one after another:
ERROR: failed to solve: failed to compute cache key: "/init.sh" not found: not found
COPY ./init.sh /usr/bin/init.sh
dockerfile: frontend/Dockerfile
path: .
Comparing this information against the actual project file layout, the cause of error is now relatively easy to spot: there is no such file ./init.sh
.
And it is now relatively easy to bind the correct path, as we knew it from the beginning:
COPY ./frontend/init.sh /usr/bin/init.sh
Learn on how to treat error messages with respect, they have a story to tell, despite how bad/or hard to read they may appear, always remember it is the best you'll get. And I always look up the references. If I don't know where the reference is at least (and expressing that knowledge with a URL is reasonable adequate for distributed systems), I'm often doing the wrong step first. It must not that I fully understand the system, but I need to know about what I know and what I not know about so I can slow down the moving target that decided to ran away and giving us an error at least. Trouble shooting 1x1.
And as we have all parts under version control here (if you don't, do that first), those hypertext references are easy to add to the commit message, which should document the driver of the change (the error message) and how we think the change addresses it (and c.f. Beams):
And just a final note: When we have fixed the error, it is easy (or easier) to say what the cause was. So in the moment of the commit and putting it to test, we can only document our little understanding. However it is important to at least document it so that even steep learning curves can be taken without losing track and going in all fresh each time of an error in (remote) CI. Feedback is too often slow to waste time with staying in the unknown. You should always only apply a fix by having the rationale of it a priori, with perhaps the exclusion that if it takes longer than three minutes - which in remote CI means it must be a single commit that did run through and was tested working within that three minutes time if you want to make a good rule of thumb out of it 3.
COPY that .
TLDR: CircleCI Docker ECR orb ERROR: failed to solve: failed to compute cache key: "/init.sh" not found