Resolving Docker Push Errors When Using Private Repository with Alpine-Based Images
While attempting to push a containerized application’s images into my private repository (registry at
registry.apprepo.app
), I encountered an error that seemed perplexing: the operation would stop unexpectedly,
indicating “EOF”. This issue arose after previously working without any problems. Below are details and steps taken
towards resolving this issue using Docker and a NGINX-alpine based setup as described in my Dockerfile
and
docker-compose.yml
.
Error Encountered:
PS C:\Users\user>\docker push registry.apprepo.app/app:1.22.3
The push refers to repository [registry.apprepo.app/app]...f4ca70ea751f: Layer already exists..EOF at http://<REPO_URL>/v2/app/blobs/uploads/{SHA}/manifest
This error suggests that some layers are present in the repository, but further push attempts to these specific image parts result in an “End of File” issue.
Dockerfile:
Here’s a snippet from my Dockerfile
which is used for building and preparing our application images before they can be
pushed upstream into the private registry. The multi-stage build includes both NodeJS (versioned at v14) as well as an
NGINX container based on Alpine Linux:
FROM node:14 as build-stage
WORKDIR /app
COPY . .
ARG target_env
RUN npm install -g gulp-cli \
&& npm install
RUN if [ "$target_env" = "development" ]; then NODE_ENV=development; export NODE_ENV | tee >>~/.npmrc ; fi
&& rm node_modules/
CMD ["sh", "-c", "/app/scripts/config.env.sh && npm start -- ${NODE_ENV}"]
Docker Compose:
Here’s the relevant docker-compose
snippet, which builds our service using a dynamic version (APP_VERSION
) and
exposes port 80 inside of it to be accessible on host as well. The build context is directed towards ./
:
version: '3'
services:
app:
image: registry.apprepo.app/${APP_VERSION} # Dynamic application versioning resolved at runtime
build:
context: ./ # Build using local directory contents as source code and dependencies
args: # Pass arguments for the target environment which is set to 'docker' here
- APP_ENV=development,NODE_ENV=${APP_ENV}
env_file: # Environment variables defined in a separate file `./docker/.env` are used during build and runtime of container.
- docker/.env
ports: # Port mapping between host machine (801) to the exposed port inside image (80).
- "8081:80" # Container's internal application serves on localhost at port `80` while external access is through mapped PORT.
Attempted Solutions and Resolution Steps Taken:
After some investigation, I identified that the root of my problem was related to using an NGINX server within our
Docker image which relies on Alpine Linux—a minimalistic but lightweight base for building container images. While this
setup had worked flawlessly before switching back from Ubuntu’s standard installations (using nginx:18.04
), it now
appears that there were compatibility issues with the private repository or its configuration settings when using NGINX
on Alpine Linux, leading to push failure due potentially incompatible server stack versions between hosting and build
environments.
To remedy this situation without significant changes from our current setup: I decided not to use an Ubuntu-based image for both builds as it would mean rewriting quite a bit of my Dockerfile—something which was unfeasible given the scale at hand (multiple services with similar dependencies). Instead, opting out and switching back directly served well.
Thus far by reverting our NGINX container images to those based on nginx:18.04
, I managed not only to resolve my
immediate issue but also maintain consistency across all service containers that share a common base image—a win for
infrastructure stability and predictability! This experience underscores the importance of environment alignment when
pushing Dockerized applications upstream into private registries, especially where custom dependencies or configurations
are involved.