Find the Best Cosmetic Hospitals

Explore trusted cosmetic hospitals and make a confident choice for your transformation.

“Invest in yourself — your confidence is always worth it.”

Explore Cosmetic Hospitals

Start your journey today — compare options in one place.

GitHub Packages Essentials — 2-Hour Hands-On Tutorial

Last Verified: September 2026
Scope: GitHub.com / GitHub Enterprise Cloud unless explicitly stated otherwise
Duration: ~2 hours including hands-on practice
Audience: Developers, DevOps engineers, platform engineers, administrators, trainers, and students
Primary hands-on registry: GitHub Container Registry (GHCR)

GitHub Packages is GitHub’s package-hosting platform. It lets teams publish, store, secure, discover, and consume software packages and container images while keeping source code, CI/CD, permissions, and package ownership close to the GitHub workflow.

This Essentials tutorial intentionally does not attempt to cover every advanced capability. It focuses on the smallest set of concepts and practical skills a learner should understand before working with GitHub Packages in real projects.


1. What You Should Be Able to Do After 2 Hours

By the end of this tutorial, you should be able to:

  1. Explain what GitHub Packages is and when to use it.
  2. Distinguish GitHub Packages from GitHub Releases and GitHub Actions artifacts.
  3. Identify the six main GitHub Packages registries.
  4. Understand granular packages vs repository-scoped packages.
  5. Explain package visibility and Read / Write / Admin permissions.
  6. Authenticate using PAT classic locally and GITHUB_TOKEN in GitHub Actions.
  7. Build, publish, and pull a container image from GHCR.
  8. Publish a container automatically using GitHub Actions.
  9. Understand cross-repository package consumption.
  10. Apply essential versioning, security, and troubleshooting practices.

2. Recommended 2-Hour Learning Flow

TimeTopicOutcome
0–10 minWhat GitHub Packages isUnderstand the problem it solves
10–25 minRegistries and package modelKnow supported ecosystems and permission models
25–40 minAuthentication and permissionsUnderstand PAT classic, GITHUB_TOKEN, package roles
40–65 minHands-on GHCRBuild, push, verify, and pull an image
65–90 minGitHub Actions publishingAutomate build-test-publish
90–105 minCross-repository accessUnderstand producer/consumer package access
105–115 minSecurity + versioning + troubleshootingLearn production habits and common failures
115–120 minKnowledge check + cheat sheetReinforce essential commands and decisions

Part 1 — Understand GitHub Packages

3. What Is GitHub Packages?

A package is a reusable software artifact that another developer, application, build, or deployment can consume.

Examples:

  • Docker / OCI container image
  • npm package
  • Maven artifact
  • Gradle-published Java library
  • NuGet package
  • Ruby gem

GitHub Packages provides registries for storing and distributing these artifacts.

Why do teams need a package registry?

Source code alone is not what applications deploy or consume.

A typical delivery path looks like this:

flowchart LR
    A[Source Code] --> B[Build]
    B --> C[Test]
    C --> D[Package]
    D --> E[Publish]
    E --> F[GitHub Packages]
    F --> G[Install / Pull]
    G --> H[Application / Deployment]
Code language: CSS (css)

A registry sits between the producer and the consumer.

  • Producer: creates and publishes a package.
  • Registry: stores package versions.
  • Consumer: installs or pulls a package.

Typical real-world example

A team builds a service called payments-api.

Instead of deploying directly from source code, CI builds a container image:

ghcr.io/acme/payments-api:1.4.2

That image is stored in GitHub Container Registry and later pulled by Kubernetes or another deployment platform.


4. GitHub Packages vs Releases vs Actions Artifacts

These three GitHub features solve different problems.

FeaturePrimary purposeBest example
GitHub PackagesReusable dependencies and deployable packagesghcr.io/acme/api:1.2.0
GitHub ReleasesRelease event, notes, downloadable assetsv1.2.0 release with binaries
GitHub Actions artifactsTemporary workflow outputsTest reports, build logs, intermediate files

Simple rule

Use GitHub Packages when another build, developer, application, or deployment will consume the artifact as a package.

Use GitHub Releases when publishing release notes and downloadable release assets.

Use Actions artifacts for files mainly associated with a workflow run.


Part 2 — Registries and Permission Models

5. Supported GitHub Packages Registries

GitHub Packages supports six principal package ecosystems.

EcosystemEndpointTypical clientPermission model
Containerghcr.ioDocker / OCIGranular user/org scoped
npmnpm.pkg.github.comnpm / YarnGranular user/org scoped
NuGetnuget.pkg.github.comdotnet / NuGetGranular user/org scoped
RubyGemsrubygems.pkg.github.comgem / BundlerGranular user/org scoped
Mavenmaven.pkg.github.comMavenRepository scoped
GradleMaven-compatible endpointGradleRepository scoped

The old Docker registry endpoint:

docker.pkg.github.com
Code language: CSS (css)

is legacy. New designs should use:

ghcr.io
Code language: CSS (css)

6. The Most Important Architecture Concept: Granular vs Repository-Scoped

This distinction changes how access control works.

flowchart TD
    A[GitHub Package] --> B{Permission model}
    B -->|Granular| C[User or Organization Scope]
    C --> D[Independent package permissions]
    C --> E[Optional repository connection]
    B -->|Repository scoped| F[Repository]
    F --> G[Repository permissions]
    F --> H[Repository visibility]

Granular packages

Supported by:

  • Container
  • npm
  • NuGet
  • RubyGems

These packages can have access rules independent of a repository.

Example:

A package can be owned by organization acme, while five different repositories receive read access.

Repository-scoped packages

Supported by:

  • Maven
  • Gradle

These packages inherit the repository’s permissions and visibility.

Remember this

Container/npm/NuGet/RubyGems = package-level access model.
Maven/Gradle = repository permission model.

This is one of the most common GitHub Packages design mistakes.


7. Package Visibility and Roles

Package roles

RoleTypical capability
ReadView metadata and download/install
WriteRead + publish/upload
AdminManage package, access, versions, deletion

Visibility

Depending on registry and account context, packages may be:

  • Public
  • Private
  • Internal

For proprietary company packages, a safe starting point is:

Private/Internal -> explicitly grant access -> make public only after review
Code language: PHP (php)

Important GHCR exception

Public GHCR container images can be pulled anonymously.

Most other GitHub Packages package-client workflows still require authentication even when a package is public.


Part 3 — Authentication

8. PAT Classic vs GITHUB_TOKEN

Authentication is where many first-time GitHub Packages users get confused.

Local package-client access

For package clients, GitHub documents personal access token (classic) authentication.

Important scopes:

ScopeUse
read:packagesDownload/install
write:packagesPublish/upload
delete:packagesDelete package/version

Example local GHCR login:

export CR_PAT="YOUR_PAT_CLASSIC"

echo "$CR_PAT" | docker login ghcr.io \
  -u YOUR_GITHUB_USERNAME \
  --password-stdin
Code language: JavaScript (javascript)

Do not hardcode the token inside scripts committed to Git.

Inside GitHub Actions

Prefer GITHUB_TOKEN whenever the package access model supports the operation.

Read-only workflow:

permissions:
  contents: read
  packages: read

Publishing workflow:

permissions:
  contents: read
  packages: write

Why GITHUB_TOKEN is preferred in Actions

It is:

  • Automatically generated
  • Short lived
  • Repository/workflow scoped
  • Permission controllable
  • Easier to audit than a shared long-lived PAT

Security rule

Local package client -> PAT classic when required
GitHub Actions -> GITHUB_TOKEN whenever possible

Part 4 — Hands-On: Publish a Container to GHCR

9. Lab 1 — Build and Publish Manually

Objective

Publish a versioned Docker image to GitHub Container Registry and pull it back successfully.

Prerequisites

You need:

  • GitHub account
  • GitHub repository
  • Docker
  • Permission to publish to the target namespace
  • PAT classic with appropriate package scope

For examples below, replace:

acme

with your GitHub username or organization.


Step 1 — Create a simple application

Create index.html:

<h1>Hello from GitHub Packages</h1>
Code language: HTML, XML (xml)

Create Dockerfile:

FROM nginx:alpine

COPY ./index.html /usr/share/nginx/html/index.html

LABEL org.opencontainers.image.source="https://github.com/acme/hello-packages"
LABEL org.opencontainers.image.description="GitHub Packages Essentials demo"
Code language: JavaScript (javascript)

The source label helps GitHub associate the image with its source repository.


Step 2 — Authenticate to GHCR

export CR_PAT="YOUR_PAT_CLASSIC"

echo "$CR_PAT" | docker login ghcr.io \
  -u YOUR_GITHUB_USERNAME \
  --password-stdin
Code language: JavaScript (javascript)

Expected result:

Login Succeeded

Step 3 — Build the image

docker build -t hello-packages:1.0.0 .
Code language: CSS (css)

Verify locally:

docker images

Step 4 — Tag the image for GHCR

docker tag hello-packages:1.0.0 \
  ghcr.io/acme/hello-packages:1.0.0

Image naming pattern:

ghcr.io/OWNER/IMAGE:TAG

Step 5 — Push the image

docker push ghcr.io/acme/hello-packages:1.0.0

Expected result:

The image layers are uploaded and GitHub creates or updates the package.


Step 6 — Verify in GitHub

Open the owner account or organization and navigate to Packages.

Confirm:

  • Package exists
  • Version 1.0.0 exists
  • Source repository is correct
  • Visibility is correct
  • Package metadata is visible

Step 7 — Pull the image

docker pull ghcr.io/acme/hello-packages:1.0.0

Run it:

docker run --rm -p 8080:80 \
  ghcr.io/acme/hello-packages:1.0.0

Open:

http://localhost:8080
Code language: JavaScript (javascript)

Expected result:

Hello from GitHub Packages
Code language: JavaScript (javascript)

10. Tag vs Digest

A container can be referenced using a tag:

ghcr.io/acme/hello-packages:1.0.0

or an immutable digest:

ghcr.io/acme/hello-packages@sha256:...

Why digest matters

Tags are human-friendly references. A digest identifies exact content.

For production deployments, digest pinning gives the strongest guarantee that the artifact being deployed is exactly the artifact that was tested.

Recommended release tags

A mature image may have:

2.4.1
2.4
2
sha-a1b2c3d
Code language: CSS (css)

Avoid using only:

latest

for production.


Part 5 — Automate Publishing with GitHub Actions

11. Why Move Publishing into CI?

Manual publishing is useful for learning, but production publishing should normally happen in CI.

Benefits:

  • Reproducible build
  • Automated testing
  • Centralized credentials
  • Audit trail
  • Controlled permissions
  • Easier provenance and security controls

Recommended lifecycle:

flowchart LR
    A[Commit / Release] --> B[Checkout]
    B --> C[Build]
    C --> D[Test]
    D --> E[Login]
    E --> F[Publish]
    F --> G[Verify]
Code language: CSS (css)

12. Lab 2 — Publish GHCR Image Using GitHub Actions

Create:

.github/workflows/publish.yml

Add:

name: Publish container

on:
  release:
    types: [published]

permissions:
  contents: read
  packages: write

jobs:
  publish:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build image
        run: |
          docker build \
            -t ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }} \
            .

      - name: Push image
        run: |
          docker push \
            ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}
Code language: HTTP (http)

What this workflow does

  1. Starts when a GitHub Release is published.
  2. Checks out the source code.
  3. Authenticates to GHCR using GITHUB_TOKEN.
  4. Builds the container.
  5. Tags it using the release tag.
  6. Publishes it to GHCR.

Why the permissions block matters

permissions:
  contents: read
  packages: write

The workflow receives only the access it needs.

Do not assume the default token permissions are sufficient.


13. Better Production Pattern: Test Before Publish

Publishing should depend on successful tests.

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - run: ./scripts/test.sh

  publish:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - uses: actions/checkout@v6
      <em># login, build, and publish steps</em>
Code language: HTML, XML (xml)

The key line is:

needs: test
Code language: HTTP (http)

If testing fails, publishing does not start.

Essential release rule

Build -> Test -> Package -> Publish

not:

Build -> Publish -> Hope tests pass

Part 6 — Cross-Repository Package Access

14. Producer and Consumer Repositories

Real organizations often separate the repository that creates a package from the repositories that consume it.

flowchart LR
    A[Producer Repo] --> B[GitHub Actions]
    B --> C[Organization Package]
    C --> D[Consumer Repo A]
    C --> E[Consumer Repo B]
    C --> F[Consumer Repo C]
Code language: CSS (css)

Example:

shared-types repo
        |
        v
@acme/shared-types
        |
   +----+----+
   |         |
payments   orders

For granular packages, GitHub lets you grant selected repositories access through package settings.

Typical cross-repository flow

  1. Publish the package from repository A.
  2. Open the package settings.
  3. Find Manage Actions access.
  4. Add repository B.
  5. Grant only the required role.
  6. In repository B, configure:
permissions:
  contents: read
  packages: read
  1. Consume the package using GITHUB_TOKEN.

Critical concept

Token scope alone is not enough.

A workflow can have:

packages: read
Code language: HTTP (http)

and still fail if the repository itself has not been granted access to the package.

Think of authorization as two layers:

Workflow token permission
        +
Package/repository access
        =
Successful package operation

Part 7 — Understand the Other Registries

15. Essential Ecosystem Examples

You do not need to master every registry during this two-hour session. You should understand the configuration pattern.

npm

Package name:

{
  "name": "@acme/shared-utils",
  "version": "1.2.0"
}
Code language: JSON / JSON with Comments (json)

.npmrc:

@acme:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}
Code language: JavaScript (javascript)

Publish:

npm publish

Install:

npm install @acme/shared-utils@1.2.0
Code language: CSS (css)

Maven

Endpoint pattern:

https://maven.pkg.github.com/OWNER/REPOSITORY
Code language: JavaScript (javascript)

Publish:

mvn --batch-mode deploy

Important: Maven packages are repository scoped.

Gradle

Publish:

./gradlew publish

Important: GitHub Gradle packages use Maven-format publishing and are repository scoped.

NuGet

Add source:

dotnet nuget add source \
  --name github \
  "https://nuget.pkg.github.com/acme/index.json"
Code language: JavaScript (javascript)

Publish:

dotnet nuget push PACKAGE.nupkg \
  --source github \
  --api-key YOUR_PAT_CLASSIC
Code language: CSS (css)

RubyGems

Registry pattern:

https://rubygems.pkg.github.com/NAMESPACE
Code language: JavaScript (javascript)

Build:

gem build package.gemspec
Code language: CSS (css)

Publish:

gem push \
  --host https://rubygems.pkg.github.com/acme \
  package.gem
Code language: JavaScript (javascript)

Part 8 — Essential Security and Release Practices

16. The 10 Rules Worth Remembering

  1. Prefer organization ownership for company packages.
  2. Prefer GITHUB_TOKEN instead of long-lived PATs in Actions.
  3. Use minimum token permissions.
  4. Publish production packages from trusted CI.
  5. Test before publishing.
  6. Do not reuse release version numbers.
  7. Use SemVer for libraries where appropriate.
  8. Use immutable container digests for production deployment.
  9. Do not store credentials in repository files.
  10. Grant consumers Read access, not Write/Admin access.

Good vs risky

RiskyBetter
Shared PATIndividual auth or GITHUB_TOKEN
Admin token for downloadsRead-only access
Publish manually from laptopControlled CI publishing
Deploy latestDeploy version + digest
Rebuild for each environmentBuild once, promote same artifact
Unlimited dev versionsRetention/cleanup policy
Package with no source linkConnect package to source repository

17. Build Once, Deploy Many

A mature delivery process promotes the same artifact through environments.

flowchart LR
    A[Commit] --> B[Build + Test]
    B --> C[Immutable Package]
    C --> D[Dev]
    D --> E[Stage]
    E --> F[Production]
Code language: CSS (css)

Do not rebuild independently for staging and production.

Why?

Because two builds from the same Git commit can still contain different dependency resolutions, timestamps, base image layers, or build-environment effects.

For containers, promote the same digest.

Good:

ghcr.io/acme/api@sha256:abc123...

Riskier:

ghcr.io/acme/api:latest

Part 9 — Troubleshooting

18. Fast Troubleshooting Matrix

ProblemLikely causeCheck
401 UnauthorizedInvalid/expired credentialToken, login, SSO authorization
Pull/install deniedMissing read accessPackage ACL + packages: read
Push deniedMissing write accessPackage role + packages: write
Works locally, fails in ActionsWorkflow token too restrictedpermissions: block
Cross-repo package not foundConsumer repo not granted accessManage Actions access
Image tag not foundWrong tag or ownerPackage page and image reference
exec format errorArchitecture mismatchImage platforms
Version already existsImmutable version collisionIncrement version
npm publishes to npmjs.orgRegistry config incorrect.npmrc / package config

Troubleshooting order

When package access fails, check in this order:

1. Correct registry endpoint?
2. Correct package name/version?
3. Authentication working?
4. Token has required scope/permission?
5. User/repository has package access?
6. Workflow permissions correct?
7. Cross-repository access configured?

This sequence prevents random trial-and-error debugging.


Part 10 — Five-Minute Final Practice

19. Mini Exercise

Assume:

  • Organization: acme
  • Producer repository: payments-api
  • Package: ghcr.io/acme/payments-api
  • Consumer repository: deployment-platform

Answer the following before checking the solution.

Questions

  1. Which registry stores the image?
  2. Is GHCR granular or repository scoped?
  3. What local token type should you use for Docker authentication?
  4. What workflow permission is required to publish?
  5. What workflow permission is required only to pull?
  6. What else must be configured when another repository consumes a private package?
  7. Which is safer for production: :latest or @sha256:...?
  8. Should production rebuild the image after staging approval?

Answers

  1. GitHub Container Registry / ghcr.io.
  2. Granular user/organization scoped.
  3. PAT classic with the required package scope.
  4. packages: write.
  5. packages: read.
  6. Grant the consumer repository package/Actions access.
  7. Immutable digest: @sha256:....
  8. No. Promote the same tested artifact.

Part 11 — Essential Cheat Sheet

20. Registry Endpoints

RegistryEndpoint
Containerghcr.io/OWNER/IMAGE
npmhttps://npm.pkg.github.com
Mavenhttps://maven.pkg.github.com/OWNER/REPOSITORY
GradleMaven-compatible GitHub Packages endpoint
NuGethttps://nuget.pkg.github.com/NAMESPACE/index.json
RubyGemshttps://rubygems.pkg.github.com/NAMESPACE

21. PAT Classic Scopes

read:packages
write:packages
delete:packages
Code language: CSS (css)

22. Workflow Permissions

Read:

permissions:
  contents: read
  packages: read

Publish:

permissions:
  contents: read
  packages: write

23. GHCR Commands

Login:

echo "$CR_PAT" | docker login ghcr.io \
  -u "$GITHUB_USER" \
  --password-stdin
Code language: PHP (php)

Build:

docker build -t ghcr.io/acme/api:1.0.0 .

Push:

docker push ghcr.io/acme/api:1.0.0

Pull:

docker pull ghcr.io/acme/api:1.0.0

Pull immutable digest:

docker pull ghcr.io/acme/api@sha256:REPLACE_WITH_DIGEST

Part 12 — What to Learn Next

24. Topics Intentionally Left for the Complete Guide

After completing this Essentials tutorial, move to the full reference guide for deeper study of:

  • Package deletion and restoration
  • REST API and gh api
  • Webhooks
  • GitHub Apps
  • Billing and storage management
  • Multi-architecture builds
  • Automated cleanup
  • Registry migration
  • Legacy Docker registry migration
  • Artifact attestations
  • SBOM
  • Dependency graph and Dependabot
  • Linked artifacts
  • Enterprise-specific behavior
  • Organization governance
  • Audit and usage reporting

These are important topics, but they are better studied after the package lifecycle, authentication model, permissions, GHCR workflow, and CI publishing process are understood.


Part 13 — Wrap-Up

25. Final Mental Model

If you remember only one flow from this tutorial, remember this:

flowchart LR
    A[Source] --> B[Build]
    B --> C[Test]
    C --> D[Package]
    D --> E[Publish with least privilege]
    E --> F[GitHub Packages]
    F --> G[Authorized Consumer]
    G --> H[Deploy exact version/digest]
Code language: CSS (css)

And remember these four rules:

1. Know the registry permission model.
2. Use the smallest required permission.
3. Publish from trusted CI.
4. Promote immutable artifacts.
Code language: JavaScript (javascript)

If those four ideas are clear, you have the foundation needed to work safely and effectively with GitHub Packages.


26. Two-Hour Completion Checklist

Before considering the Essentials session complete, verify that the student can answer Yes to the following:

  • [ ] I can explain what GitHub Packages is.
  • [ ] I know when to use Packages vs Releases vs Actions artifacts.
  • [ ] I know the six supported package ecosystems.
  • [ ] I know which registries are granular and which are repository scoped.
  • [ ] I understand Read / Write / Admin package roles.
  • [ ] I understand PAT classic vs GITHUB_TOKEN.
  • [ ] I can log in to GHCR.
  • [ ] I can build, tag, push, and pull an image.
  • [ ] I can publish an image using GitHub Actions.
  • [ ] I understand cross-repository package access.
  • [ ] I understand why production should use immutable versions/digests.
  • [ ] I know the first checks to make when authentication or authorization fails.

27. Source

This Essentials tutorial is a condensed learning path derived from the GitHub Packages — Complete Reference Guide & Hands-On Tutorial, last verified September 2026. It intentionally prioritizes foundational concepts and hands-on skills suitable for a two-hour study/practice session rather than reproducing the complete advanced reference.

Find Trusted Cardiac Hospitals

Compare heart hospitals by city and services — all in one place.

Explore Hospitals
I'm Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms. I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.

Related Posts

GitHub Organization Administration Essentials — 2-Hour Tutorial

Last Verified: September 2026Based on: GitHub Organization Administration — Complete Reference Guide and TutorialDuration: 2 hoursAudience: GitHub organization owners, DevOps/platform engineers, developers with delegated administration duties, security administrators, and technical trainers….

Read More

GitHub Projects Essentials — 2-Hour Tutorial & Hands-On Guide

Scope: Current GitHub Projects / Projects v2, not Projects (classic).Audience: Developers, DevOps engineers, engineering managers, product managers, project administrators, and GitHub organization members.Training duration: Approximately 2 hours, including guided practice.Prerequisite: Basic familiarity with…

Read More

GitHub Actions Essentials — Learn CI/CD in 2 Hours

Audience: Beginners, developers, junior DevOps engineers, QA engineers, and students Level: Beginner to early-intermediate Duration: About 120 minutes Format: Learn, modify, run, break, and fix Goal: By…

Read More

GitHub Actions — CI/CD Automation & DevOps Engineering

Course Duration 2 Days | 16 Hours Format: Instructor-Led Training + Hands-on Labs + Real-World CI/CD Project Offered By DevOpsSchool Website: DevOpsSchool GitHub Actions — CI/CD Automation…

Read More

Top 10 AI UI-to-Code Generators: Features, Pros, Cons & Comparison

Introduction AI UI-to-Code Generators help designers, developers, product teams, and startups convert visual designs, screenshots, wireframes, Figma files, sketches, or natural language prompts into usable frontend code….

Read More
Subscribe
Notify of
guest
0 Comments
Newest
Oldest Most Voted
0
Would love your thoughts, please comment.x
()
x