Saltar a contenido

15 - Your First Contribution

What this session is

The whole thing. We walk through making a real contribution to a real containerized OSS project, end-to-end.

The workflow

Identical to the workflow in the other beginner paths:

  1. Fork on GitHub.
  2. Clone your fork.
  3. Add upstream as remote.
  4. Branch off main.
  5. Set up: ensure docker build works on a fresh clone.
  6. Change the Dockerfile / compose.yaml / docs.
  7. Test locally: rebuild, run, verify nothing broke.
  8. Push to your fork; open PR.

Step 1: Fork & clone

GitHub → Fork (top right). Then:

git clone git@github.com:<you>/<project>.git
cd <project>
git remote add upstream git@github.com:<owner>/<project>.git
git fetch upstream

Step 2: Branch

git checkout -b fix/dockerfile-non-root-user

Branch names should hint at the change.

Step 3: Verify the baseline

docker build -t test:before .

Should succeed. If it doesn't on a fresh clone, fix that first (or ask in the issue).

Step 4: Make the change

Edit the Dockerfile. Suppose your change is "add a non-root user." Before:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]

After:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

RUN useradd --create-home --shell /bin/bash --uid 1001 app && \
    chown -R app:app /app
USER 1001:1001

CMD ["python", "app.py"]

Step 5: Test

docker build -t test:after .
docker run --rm test:after id           # should report uid=1001
docker run --rm test:after python app.py    # should still work

If the app needs to write somewhere (e.g. a cache dir), confirm permissions are correct.

If the project has a compose.yaml, test that too:

docker compose up -d
docker compose logs -f
# verify the app works
docker compose down

Step 6: Run CI's checks locally

Open the CI workflow (.github/workflows/*.yml). Whatever it runs, run those commands too:

  • docker buildx build --platform linux/amd64,linux/arm64 . - multi-arch test.
  • hadolint Dockerfile - Dockerfile linter (install: brew install hadolint or use the Docker image).
  • trivy image test:after - vulnerability scan.

If any fail, fix before pushing.

Step 7: Commit & push

git add Dockerfile
git commit -m "Dockerfile: run as non-root user (UID 1001)"
git push origin fix/dockerfile-non-root-user

Commit message conventions vary by project. Some require Conventional Commits (fix:, feat:); most don't.

Step 8: Open the PR

On the upstream repo, click "Compare & pull request."

  • Title. Mirror the commit message.
  • Description. What changed, why, how you tested. If there's a related issue: Closes #123.
  • Checklist. Address every item in the PR template.

Submit. CI runs. Fix anything red by pushing more commits to the same branch.

What review looks like

A maintainer reads. Outcomes: 1. "LGTM, merging." Done. 2. "Could you change these?" Most common. Address each comment, push commits. 3. "Not what we want." Rare for good first issue work. Ask about related work. 4. Silence. Polite check-in after 1 week; escalate after 3.

Address feedback efficiently. Disagree only on substance.

After the merge

  • Update your fork's main.
  • Delete the branch.
  • Take a screenshot.
  • Sit with it for a day.

Worked example: contributing to docker-library/python (hypothetical)

Suppose you noticed docker-library/python doesn't have an example in its README for using build arguments to pin a Python patch version. You decide to add one.

git clone git@github.com:<you>/docker-python.git
cd docker-python
git remote add upstream git@github.com:docker-library/python.git
git fetch upstream

git checkout -b docs/add-build-arg-example

# Edit README.md, add the example.

# Test that the README renders correctly (markdown preview in your editor).

git add README.md
git commit -m "Add example: pinning Python patch version via build-arg"
git push origin docs/add-build-arg-example

Open PR. Wait for review. Address style nits ("please use fenced code blocks with dockerfile language tag"). Push fixes. Merge.

You're now a docker-library contributor.

After your first PR: what next

  1. Pick another issue in the same project. Familiarity compounds.
  2. After 3-5 PRs, become a regular. Watch issues, help others, review PRs (you don't need maintainer permissions to leave helpful comments).
  3. Branch out to Tier 3-4 projects.
  4. Build your own containerized service. Publish the image. Maintain the Dockerfile.
  5. Pick the next path: Kubernetes From Scratch is the natural follow-up.

What you might wonder

"PR sits for weeks?" Polite check-in after 1 week. After 3, ask in the project's chat/discussions.

"My change broke CI?" Read the failing job's logs. Fix locally, push another commit. The PR updates automatically.

"Maintainer rude?" Disengage. Try another project.

"Can I list this on a CV?" Yes - link to specific merged PRs.

Done with this path

You've: - Installed Docker, run your first containers. - Built your own images with Dockerfile. - Used volumes, networks, ports. - Composed multi-container apps. - Published images to a registry. - Read a real containerized OSS project. - Submitted a PR.

What you should do next: keep using containers daily. Use them for development, for ad-hoc tools, for experiments. Familiarity compounds.

Recommended next paths on this site:

  • Kubernetes From Scratch - containers' big sibling. Orchestration, scaling, declarative deploys.
  • Container Internals - senior reference path. How containers actually work (namespaces, cgroups, OCI, runtimes). Assumes you've done this path.
  • Linux Kernel - the substrate. Containers ARE Linux features.

Congratulations. You are no longer a beginner.

Comments