Skip to content

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.


Previous Post
502 Server Error encountered when deploying a NET
Next Post
Understanding Project Access Tokens in GitLab A T