Fading Coder

An Old Coder’s Final Dance

Home > Tech > Content

Pushing Docker Images to Private Registries

Tech 3

This guide shows how to push images to a private repository by tagging them with the correct repository name (and registry host when needed) and then pushing with Docker CLI. It also includes examples for Docker Hub, self‑hosted registries, and Maven-based automation.

Core commands and tagging syntax

  • Tag syntax
docker tag [OPTIONS] SOURCE_IMAGE[:TAG] [REGISTRY_HOST[:PORT]/][NAMESPACE/]REPO[:TAG]
  • Push syntax
docker push [REGISTRY_HOST[:PORT]/][NAMESPACE/]REPO[:TAG]

If you’re pushing to Dockeer Hub, the namespace is your Docker Hub username or organization. For private/self‑hosted registries, include the registry host (and port if not 443/HTTPS default).

Pushing to a private repo on Docker Hub

  1. Create the repository on Docker Hub and mark it private, or set your account’s default visibility for new repos to "private". You must have available private repo quota on your plan.
  2. Log in from the CLI:
docker login
  1. Tag you're local image with your namespace and repo name, then push:
# Example: tag by IMAGE ID or existing local image name
docker tag 518a41981a6a myuser/api-service:1.0.0

docker push myuser/api-service:1.0.0

Notes:

  • Always include your namespace (e.g., myuser/…). Omitting it may refer to a public root namespace you don’t control.
  • If the repo doesn’t exist and your default visibility is public, the pushed repo will be public unless you created it as private beforehand or changed default visibility.

Pushing to a private, self‑hosted registry

  1. Log in to the specific registry:
docker login registry.internal.example.com:5000
  1. Tag with the registry host and port, then push:
# Tag an image by ID with the registry hostname/port
docker tag 19fcc4aa71ba registry.internal.example.com:5000/payments/backend:0.3.2

docker push registry.internal.example.com:5000/payments/backend:0.3.2

Minimal three‑step workflow (Docker Hub)

# 1) Authenticate
docker login --username myuser

# 2) Tag the image with your namespace/repo
docker tag my-local-image myuser/my-repo:latest

# 3) Push to Docker Hub
docker push myuser/my-repo:latest

Alternative: committing a runing container to an image (not recommended for reproducible builds)

Prefer Dockerfiles for deterministic builds. If you must capture a container state:

# Create a new image from a running container’s filesystem
docker commit <CONTAINER_ID> myuser/snapshot-image:debug

# Optional: run it to test
docker run -it --rm myuser/snapshot-image:debug

# Log in and push
docker login
docker push myuser/snapshot-image:debug

Automating with Maven (Fabric8 Docker Maven Plugin)

Below are two approaches using the Fabric8 Docker Maven Plugin: one to build and push manually via goals, and one that binds build/push to Maven phases.

Option A: Build via Maven and push via explicit goal

Example profile in your parent pom.xml:

<profiles>
  <profile>
    <id>docker-build</id>
    <build>
      <plugins>
        <plugin>
          <groupId>io.fabric8</groupId>
          <artifactId>docker-maven-plugin</artifactId>
          <version>0.43.4</version>
          <configuration>
            <images>
              <image>
                <!-- docker.io implies Docker Hub; you can parameterize registry/namespace -->
                <name>${docker.registry}/${docker.namespace}/orders-app:1.0.0</name>
                <build>
                  <dockerFileDir>${project.basedir}/src/docker/orders-app</dockerFileDir>
                  <assembly>
                    <inline>
                      <fileSets>
                        <fileSet>
                          <directory>${project.build.directory}</directory>
                          <outputDirectory>.</outputDirectory>
                          <includes>
                            <include>*.jar</include>
                          </includes>
                        </fileSet>
                      </fileSets>
                    </inline>
                  </assembly>
                </build>
              </image>
            </images>
          </configuration>
          <executions>
            <execution>
              <id>build-image</id>
              <phase>package</phase>
              <goals>
                <goal>build</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
    <properties>
      <docker.registry>docker.io</docker.registry>
      <docker.namespace>myuser</docker.namespace>
    </properties>
  </profile>
</profiles>

Build then push from the project directory:

mvn -Pdocker-build clean package
mvn -Pdocker-build docker:push

Ensure you’re logged in via docker login so the plugin can use your Docker credentials (stored in your Docker config file, typically ~/.docker/config.json).

Option B: Build and push bound to Maven phases

This binds image build to package and push to install so a single command both builds and pushes.

<profiles>
  <profile>
    <id>docker-build</id>
    <build>
      <plugins>
        <plugin>
          <groupId>io.fabric8</groupId>
          <artifactId>docker-maven-plugin</artifactId>
          <version>0.43.4</version>
          <configuration>
            <images>
              <image>
                <name>${docker.registry}/${docker.namespace}/orders-app:1.0.0</name>
                <build>
                  <dockerFileDir>${project.basedir}/src/docker/orders-app</dockerFileDir>
                  <assembly>
                    <inline>
                      <fileSets>
                        <fileSet>
                          <directory>${project.build.directory}</directory>
                          <outputDirectory>.</outputDirectory>
                          <includes>
                            <include>*.jar</include>
                          </includes>
                        </fileSet>
                      </fileSets>
                    </inline>
                  </assembly>
                </build>
              </image>
            </images>
          </configuration>
          <executions>
            <execution>
              <id>docker-build</id>
              <phase>package</phase>
              <goals>
                <goal>build</goal>
              </goals>
            </execution>
            <execution>
              <id>docker-push</id>
              <phase>install</phase>
              <goals>
                <goal>push</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
    <properties>
      <docker.registry>docker.io</docker.registry>
      <docker.namespace>myuser</docker.namespace>
    </properties>
  </profile>
</profiles>

Run:

mvn -Pdocker-build clean install

Tip: Avoid also invoking docker:push explicitly if you’ve already bound it to a build phase to prevent duplicate pushes. If your Java artifact uses timestamped snapshots, ensure the Dockerfile or plugin assembly picks up the expected JAR name.

Example Dockerfile (Java application)

FROM eclipse-temurin:17-jre

# Optional: set a working directory
WORKDIR /opt/app

# Copy the built JAR into the image (matches Maven assembly above)
COPY *.jar app.jar

# Run the application
ENTRYPOINT ["java", "-jar", "app.jar"]

Self‑hosted registry example (full flow)

# Log in to the private registry
docker login registry.private.local:5443

# Build a local image
docker build -t checkout-service:0.9.0 ./services/checkout

# Tag it for the registry
docker tag checkout-service:0.9.0 registry.private.local:5443/team/checkout:0.9.0

# Push the image
docker push registry.private.local:5443/team/checkout:0.9.0

Common pitfalls

  • Wrong namespace: Always tag as namespace/repo (e.g., myuser/myrepo) for Docker Hub.
  • Repo visibility: If you rely on implicit repo creation, check your acccount’s default visibility or pre‑create the repo as private.
  • Duplicate pushes in Maven: Don’t bind docker:push to a phase and also run docker:push as a standalone goal in the same build.
  • Registry host omitted: For self‑hosted/private registries, include the registry host (and port) when tagging and pushing.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.