Skip to content

Conversation

@TheFox0x7
Copy link
Contributor

add mount cache directives to container builds, which speeds up local builds bypassing node and go package download entirely on second build and caching go compilation.
drop job level split on regular/rootless, which allows to reuse the previously made stage for rootless, skipping duplicate builds in CI.

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Oct 18, 2025
@TheFox0x7
Copy link
Contributor Author

replaces #34876 and #27998 to a lesser degree.

I've tried to trim down CI time further but I can either optimize for local or CI builds because dockers caching system allows to push layers to registry but it does not allow to share mounted cache in any way. I've tried using one action to do so but it did not work at all and maybe for the better as juggling the cache wouldn't be too fun if something went wrong.

It would be possible to optimize for layers here (which I've sort of done) and have them pushed to registry on nightly builds then pulled during every other one but it then removes the mountable cache completely as when both are used they are unreliable (cache is empty and layers apply as if it worked).

@TheFox0x7 TheFox0x7 marked this pull request as ready for review October 18, 2025 17:48
Copy link
Member

@lunny lunny Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These files change maybe added accidentally?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no that's to avoid having to set permissions during build.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the chmod was there for Windows developers? Windows git clone doesn't have "+x" mod?

(Just a guess, correct me if I was wrong)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was introduced in #27757 and I don't see any explanation so... I have no idea either.

Since CI builds on linux I'm not that concerned with potential windows issues in here, especially since this unifies the build stage (which I did not merge into a single file here because it didn't feel like much gain - I could though if you think it's worth it).
If someone with windows wants to try it and it's a problem, I'll work on a solution.

Copy link
Contributor

@wxiaoguang wxiaoguang Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is older than that, see chmod executables when copying to the docker #17423

And there were some Windows developers ("make fmt" fails on windows #14438, Some file perms are incorrect in the docker image built from Windows #17400), I don't know whether as of today whether Windows developers need to build container image, and/or whether the "chmod" need the tricks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imho, the only supported development environment on Windows should be WSL, these other stuff are usually "git bash" etc, which are fake Linux environments and imho do not have to be supported.

Dockerfile Outdated

RUN make frontend

# Copy source files
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need to copy sub directories one by one? I think .dockerginore can work well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to avoid copying entire .git directory, it's not possible to bind it if it's in dockerignore sadly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe related #35697 (comment)

But I think the shallow clone's ".git" directory won't be too large? And why it can't mount the source directory directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mount didn't work for some reason though it should've (reason being it tried to write to read-only stuff but theoretically it should just layer on the read only items and persist to later stage) . I'll tinker with it some more as pure mount would be simplest to work with

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this copying belongs in the Makefile, not in this docker file. You have various variables like GO_DIRS there that should be helpful. Maybe call it make docker-copy or something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow - you mean like bind the source to the container and call make docker-copy to copy it from a bind mount to a layer?
What would be the point?

Copy link
Member

@silverwind silverwind Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's about consolidating such logic into the Makefile to have shared variables like GO_DIRS which are easier to maintain than having logic spread in multiple files where they can go out of sync.

Once you have make and Makefile available in your container, you can run make targets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the copying in favor on excluding git during copy (which is why the docker syntax directive is there). I'll have to rereview if the container is 1:1 with the nightly.
Also excluded the actual container files from being copied since every edit triggered a full rebuild from copy stage even if the change was in later stages.

@lunny lunny added this to the 1.26.0 milestone Oct 20, 2025
@lunny lunny added the topic/build PR changes how Gitea is built, i.e. regarding Docker or the Makefile label Oct 20, 2025
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
annotations: |
org.opencontainers.image.authors="maintainers@gitea.io"
Copy link
Member

@silverwind silverwind Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just add this to the Dockerfiles instead:

LABEL org.opencontainers.image.authors="maintainers@gitea.io"

Ref: https://docs.docker.com/reference/build-checks/maintainer-deprecated/

Copy link
Member

@silverwind silverwind Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, Dockerfiles do already have a maintainer label:

LABEL maintainer="maintainers@gitea.io"

It's probably better to use org.opencontainers.image.authors instead, but definitely not two labels for the same thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it to tag generation to avoid having implicitly marking user built containers as maintained by gitea, but I can move back into the container if it's not a concern.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm makes sense your way I guess. Would just like to avoid duplication.

It's not required and grows over time.
Also exclude containerfiles from the copy so changes in them won't
trigger layer invalidation if it's not needed
Comment on lines +59 to +60
COPY docker/rootless /
COPY --from=build-env --chmod=755 --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
Copy link
Contributor

@wxiaoguang wxiaoguang Oct 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think we can(should) support "chmod a+x /.../scripts" in "build-env"

Then here we only need to

COPY --from=build-env /.../docker/rootless /
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea

It looks clearer (everything is well prepared in "build-env")

Then Windows Docker users are also satisfied.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make it into a separate stage then - I'd rather keep the build 1:1 between variants.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure whether a separate stage is really needed. It also makes sense that the files in build-env have correct file modes.

If you see more values by a separate stage, that's also pretty fine.

RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target="/root/.cache/go-build" \
--mount=type=cache,target=/root/.local/share/pnpm/store \
--mount=type=bind,source=".git/",target=".git/" \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as mount bind works, then the project root can be fully mounted into the builder image, then no COPY --exclude=.git/ . . is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bind is... wonky IMO for a lack of a better word. It works but it's readonly so I have to swap it to rw mode and move the binary so it's not discarded after build.
Even after all this I won't be able to build it seamlessly with anything besides docker/buildkit due to buildah not caring about dockerignore when using bind mounts for some reason.

RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target="/root/.cache/go-build" \
    --mount=type=cache,target=/root/.local/share/pnpm/store \
    --mount=type=bind,source="./",target="./",rw \
    if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
    && make && mv gitea /

# -- snip --

COPY --chmod=755 --from=build-env /gitea /app/gitea/gitea

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm yes, node_modules seems to be a problem. Maybe we can leave a comment here to explain why sometimes "copy" sometimes "mount .git"

@wxiaoguang
Copy link
Contributor

wxiaoguang commented Oct 29, 2025

By the way, to speed up the "github actions release", I can see a much faster approach:

  1. Build release binaries first (they will be released to https://dl.gitea.com/gitea/)
  2. Use these pre-built binaries and just copy them into the container image, no need to build anymore.

(The container build cache can still be supported for developers who need to build the images by themselves)

@TheFox0x7
Copy link
Contributor Author

How would you keep it sane though? It is a good idea (though I thought of it in inverse - take binaries from docker nvm windows builds exist). But I don't see how you'd add the binary without another Dockerfile with ADD for remote resource. That could replace the existing ones sure but then I can't exactly make my own container.
How do you see it?

@wxiaoguang
Copy link
Contributor

Just an idea 😄 not sure whether it brings enough value

@TheFox0x7
Copy link
Contributor Author

TheFox0x7 commented Oct 29, 2025

I'd say it does but inverse (binary from container) would be simpler to do (safe for windows builds). I can look at it later.

Is the git checkout in container even used btw? I don't exactly see a usecase for it...
I mean I do but I'm not sure why would someone use that instead of checking out the version with git. Maybe I'm missing something?

@wxiaoguang
Copy link
Contributor

wxiaoguang commented Oct 29, 2025

Is the git checkout in container even used btw? I don't exactly see a usecase for it... I mean I do but I'm not sure why would someone use that instead of checking out the version with git. Maybe I'm missing something?

Agree with you. That checkout came from "Docker multi-stage (#2927)", it seems no real use case for it.

  • permit to chose the version of the binary build via --build-arg GITEA_VERSION=v1.2.3

If removing it can make the whole system simpler, maybe it's fine to remove it.

If removing it doesn't simplify, maybe it can still be kept for a while.


Update: it just conflicts the GITEA_VERSION used by Makefile:

  • In Makefile, GITEA_VERSION means always set it as the version, no matter what commit it uses
  • In Dockerfile, GITEA_VERSION means "checkout the target branch" .....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. modifies/internal topic/build PR changes how Gitea is built, i.e. regarding Docker or the Makefile

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants