Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GitHttpServer broken by git/git-daemon Alpine update #105

Closed
harmonic-jamie opened this issue May 16, 2024 · 8 comments · Fixed by #106
Closed

GitHttpServer broken by git/git-daemon Alpine update #105

harmonic-jamie opened this issue May 16, 2024 · 8 comments · Fixed by #106
Labels
bug Something isn't working

Comments

@harmonic-jamie
Copy link
Contributor

Affected version(s): at least 0.6.0 & 0.5.0.

When running the GitHttpServer, it fails when the Docker image is built with the following exception:

#5 [2/2] RUN  apk add --update nginx &&      apk add --update git-daemon &&      apk add --update fcgiwrap &&      apk add --update spawn-fcgi &&      apk add --update openssl &&      rm -rf /var/cache/apk/*
#5 0.312 fetch https://dl-cdn.alpinelinux.org/alpine/v3.19/main/x86_64/APKINDEX.tar.gz
#5 0.494 fetch https://dl-cdn.alpinelinux.org/alpine/v3.19/community/x86_64/APKINDEX.tar.gz
#5 0.771 (1/2) Installing pcre (8.45-r3)
#5 0.820 (2/2) Installing nginx (1.24.0-r16)
#5 0.842 Executing nginx-1.24.0-r16.pre-install
#5 0.897 Executing nginx-1.24.0-r16.post-install
#5 0.900 Executing busybox-1.36.1-r15.trigger
#5 0.905 OK: 26 MiB in 37 packages
#5 1.319 ERROR: unable to select packages:
#5 1.319   git-2.43.0-r0:
#5 1.319     breaks: git-daemon-2.43.4-r0[git=2.43.4-r0]
#5 1.319             git-daemon-2.43.4-r0[git=2.43.4-r0]
#5 1.319     satisfies: world[git=2.43.0-r0]
#5 ERROR: process "/bin/sh -c apk add --update nginx &&      apk add --update git-daemon &&      apk add --update fcgiwrap &&      apk add --update spawn-fcgi &&      apk add --update openssl &&      rm -rf /var/cache/apk/*" did not complete successfully: exit code: 2
------
 > [2/2] RUN  apk add --update nginx &&      apk add --update git-daemon &&      apk add --update fcgiwrap &&      apk add --update spawn-fcgi &&      apk add --update openssl &&      rm -rf /var/cache/apk/*:
0.820 (2/2) Installing nginx (1.24.0-r16)
0.842 Executing nginx-1.24.0-r16.pre-install
0.897 Executing nginx-1.24.0-r16.post-install
0.900 Executing busybox-1.36.1-r15.trigger
0.905 OK: 26 MiB in 37 packages
1.319 ERROR: unable to select packages:
1.319   git-2.43.0-r0:
1.319     breaks: git-daemon-2.43.4-r0[git=2.43.4-r0]
1.319             git-daemon-2.43.4-r0[git=2.43.4-r0]
1.319     satisfies: world[git=2.43.0-r0]
------
Dockerfile:3
--------------------
   2 |     
   3 | >>> RUN  apk add --update nginx && \
   4 | >>>      apk add --update git-daemon && \
   5 | >>>      apk add --update fcgiwrap && \
   6 | >>>      apk add --update spawn-fcgi && \
   7 | >>>      apk add --update openssl && \
   8 | >>>      rm -rf /var/cache/apk/*
   9 |     
--------------------
ERROR: failed to solve: process "/bin/sh -c apk add --update nginx &&      apk add --update git-daemon &&      apk add --update fcgiwrap &&      apk add --update spawn-fcgi &&      apk add --update openssl &&      rm -rf /var/cache/apk/*" did not complete successfully: exit code: 2

The issue is reproduced by running the GitHttpServerContainerTest within the repository itself.

[ERROR] com.github.sparsick.testcontainers.gitserver.http.GitHttpServerContainerTest.cloneWithAuthenticationFailedWithoutCredential(GitServerVersions)[1] -- Time elapsed: 4.910 s <<< ERROR!
org.testcontainers.containers.ContainerFetchException: Can't get Docker image: RemoteDockerImage(imageName=<resolving>, imagePullPolicy=DefaultPullPolicy(), imageNameSubstitutor=org.testcontainers.utility.ImageNameSubstitutor$LogWrappedImageNameSubstitutor@4b511e61)
        at org.testcontainers.containers.GenericContainer.getDockerImageName(GenericContainer.java:1364)
        at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:359)
        at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:330)
        at com.github.sparsick.testcontainers.gitserver.http.GitHttpServerContainerTest.cloneWithAuthenticationFailedWithoutCredential(GitHttpServerContainerTest.java:44)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
        at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: com.github.dockerjava.api.exception.DockerClientException: Could not build image: The command '/bin/sh -c apk add --update nginx && apk add --update git-daemon &&apk add --update fcgiwrap &&apk add --update spawn-fcgi && apk add --update openssl && rm -rf /var/cache/apk/*' returned a non-zero code: 2
        at com.github.dockerjava.api.command.BuildImageResultCallback.getImageId(BuildImageResultCallback.java:71)
        at com.github.dockerjava.api.command.BuildImageResultCallback.awaitImageId(BuildImageResultCallback.java:50)
        at org.testcontainers.images.builder.ImageFromDockerfile.resolve(ImageFromDockerfile.java:163)
        at org.testcontainers.images.builder.ImageFromDockerfile.resolve(ImageFromDockerfile.java:42)
        at org.testcontainers.utility.LazyFuture.getResolvedValue(LazyFuture.java:20)
        at org.testcontainers.utility.LazyFuture.get(LazyFuture.java:41)
        at org.testcontainers.shaded.com.google.common.util.concurrent.Futures$1.get(Futures.java:536)
        at org.testcontainers.images.RemoteDockerImage.getImageName(RemoteDockerImage.java:168)
        at org.testcontainers.images.RemoteDockerImage.resolve(RemoteDockerImage.java:72)
        at org.testcontainers.images.RemoteDockerImage.resolve(RemoteDockerImage.java:33)
        at org.testcontainers.utility.LazyFuture.getResolvedValue(LazyFuture.java:20)
        at org.testcontainers.utility.LazyFuture.get(LazyFuture.java:41)
        at org.testcontainers.containers.GenericContainer.getDockerImageName(GenericContainer.java:1362)
        ... 43 more
@harmonic-jamie
Copy link
Contributor Author

It looks to me as if the git and git-daemon APK's were updated very recently (15-May) and that has likely caused the issue.

https://pkgs.alpinelinux.org/packages?name=git&branch=v3.19&repo=&arch=&maintainer=

@harmonic-jamie
Copy link
Contributor Author

this seems specific to GitServerVersions.V2_43 - tests pass for the older versions.

@sparsick sparsick added the bug Something isn't working label May 16, 2024
@harmonic-jamie
Copy link
Contributor Author

Have raised PR #106

This doesn't (yet) fully fix the issue as although the container now builds successfully, the same tests fail with a different exception.

Workaround for other users of this testcontainers module is to avoid GitServerVersions.V2_43 and use V2_40 instead.

Error when running tests:

[ERROR] com.github.sparsick.testcontainers.gitserver.http.GitHttpServerContainerTest.cloneWithAuthentication(GitServerVersions)[1] -- Time elapsed: 8.264 s <<< ERROR!
org.eclipse.jgit.api.errors.TransportException: http://localhost:32818/git/testRepo: 500 Internal Server Error
        at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:249)
        at org.eclipse.jgit.api.CloneCommand.fetch(CloneCommand.java:319)
        at org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:189)
        at com.github.sparsick.testcontainers.gitserver.http.GitHttpServerContainerTest.cloneWithAuthentication(GitHttpServerContainerTest.java:65)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
        at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: org.eclipse.jgit.errors.TransportException: http://localhost:32818/git/testRepo: 500 Internal Server Error
        at org.eclipse.jgit.transport.TransportHttp.connect(TransportHttp.java:729)
        at org.eclipse.jgit.transport.TransportHttp.openFetch(TransportHttp.java:466)
        at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:153)
        at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:105)
        at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1482)
        at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:238)
        ... 43 more

Failing tests are the V2_43 versions of:

[ERROR] Errors: 
[ERROR]   GitHttpServerContainerTest.cloneWithAuthentication:65 » Transport http://localhost:32818/git/testRepo: 500 Internal Server Error
[ERROR]   GitHttpServerContainerTest.cloneWithoutAuthentication:34 » Transport http://localhost:32812/git/testRepo: 500 Internal Server Error

Tests for all versions pass for the test cloneWithAuthenticationFailedWithoutCredential - which is interesting.

I haven't been able to find logs from within the container itself to explain why it is returning a 500 status code, yet.

@sparsick
Copy link
Owner

Thanks @harmonic-jamie for your analysis. I will also take a look at it.

@sparsick
Copy link
Owner

I could check the access log of the nginx.

172.17.0.1 - - [17/May/2024:12:34:30 +0000] "GET /git/testRepo/info/refs?service=git-upload-pack HTTP/1.1" 500 5 "-"
 "git/2.45.0"

unfortunately not very helpful

@harmonic-jamie
Copy link
Contributor Author

i've tweaked the CMD added by the GitHttpServer when it builds the image as follows:

            tempBuilder.cmd("spawn-fcgi -s /run/fcgi.sock -- /usr/bin/fcgiwrap -f && " +
                            "    nginx -g \"daemon off;\"")

Note the -- and the -f on the end of fcgiwrap. The -- seems to be recommended by the man file.

-f
Filename of the FastCGI application to spawn. This option is deprecated and it is recommend to always specify the application (absolute path) and its parameters after "--"; the fcgiapp parameter is directly used for the exec() call, while for starting the binary given with -f /bin/sh is needed (which may not be available in a chroot).

The -f option seems to direct logs to stderr - found here: https://serverfault.com/a/738930

That has given me this in the nginx error.log:

2024/05/17 15:31:48 [error] 18#18: *1 FastCGI sent in stderr: "fatal: detected dubious ownership in repository at '/srv/git/testRepo.git'
To add an exception for this directory, call:

	git config --global --add safe.directory /srv/git/testRepo.git" while reading response header from upstream, client: 172.17.0.1, server: 9ab9cdce7e72, request: "GET /git/testRepo/info/refs?service=git-upload-pack HTTP/1.1", upstream: "fastcgi://unix:/run/fcgi.sock:", host: "localhost:32965"

Ownership of that folder appears to be git.

/ # cd /srv/git/
/srv/git # ls -alh
total 0      
drwxr-xr-x    1 git      git           24 May 17 15:49 .
drwxr-xr-x    1 git      git            6 May 17 15:49 ..
drwxr-xr-x    1 git      git           98 May 17 15:49 testRepo.git

But the user running nginx and fastcgi is root. Which might be the problem.

This can be circumvented with, which I'll add to my PR.

@harmonic-jamie
Copy link
Contributor Author

to finish my last sentence...
This error can be circumvented by disabling safe.directory warnings, which I've added to my PR #106 .

Earlier in the last comment I mention two -f switches. The first relates to spawn-fcgi the second relates to fcgiwrap.

@sparsick
Copy link
Owner

Thanks for the analysis.

But the user running nginx and fastcgi is root. That could be the problem.

I will test this next week. If it is possible, run nginx as git user as well. But meanwhile, how you're dealing with it is okay for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants