-
-
Notifications
You must be signed in to change notification settings - Fork 294
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
[Bug]: ImageFromDockerfileBuilder cannot build Dockerfile
with intermediate layer (regression works with 3.3.0
)
#972
Comments
You can pass the build context via |
Yes, but building the Dockerfile will fail that way. I think, that |
Does that help? |
Thank you for your help :) PS C:\Users\User\testcontainers\example> docker build --tag SomeTag -f "dir/dir/Dockerfile" . And IFutureDockerImage futureImage = new ImageFromDockerfileBuilder()
.WithDockerfileDirectory("/Users/testcontainers/example")
.WithDockerfile("dir/dir/Dockerfile")
.Build();
await futureImage.CreateAsync()
.ConfigureAwait(false); Throws the exception (when creating the
The Dockerfile is a regular Dockerfile for running an ASPNET Web Api. It copies the files, restores, builds and publishes the application. So I am confused by the exception about pulling. |
This sounds like Docker cannot pull the dependent images from in the |
I don't point to private registries and only use It works with version For my background: I have a solution with a web app and a web api. The web app calls the api. For some integration tests I want to start both apps in containers and make requests to the web app. This way, I want to test, if the the web app can call the api and if everything fits together. |
This sounds odd. It might be a regression in version Can you share the |
Sure, here is the Dockerfile: FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["MySoftware/Source/MyApi/MyApi/MyApi.csproj", "MySoftware/Source/MyApi/MyApi/"]
RUN dotnet restore "MySoftware/Source/MyApi/MyApi/MyApi.csproj"
COPY . .
WORKDIR "/src/MySoftware/Source/MyApi/MyApi"
RUN dotnet build "MyApi.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "MyApi.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApi.dll"] I am using Visual Studio and XUnit. What kind of log messages do you mean? Here is the test output (when using testcontainers version
|
Thank you, that really helped me understand the problem much better. Testcontainers for .NET, tries to download each image from the I am curious about how we can identify these intermediate build layers. @eddumelendez , do you have any idea how Java does it? Do we need to skip pulling images when we find the image name after the |
Ah, I understand the problem now. Thank you for that explanation. Can I help in another way? I don't really want to remove those intermediate layers, because they improve performance, and separate concerns, if I understand them correctly (Visual Studio automatically adds them when creating the Dockerfile). Would you still remove those layers or just work with the version |
I intended that as a workaround, not as a final solution 😄. Of course, the upcoming version of Testcontainers for .NET should address the issue with the intermediate layers appropriately.
I am considering a way to figure out the names of the intermediate layers, then we can skip those layers (images) here. |
I am not an expert with regular expressions, nor with the Dockerfile syntax. But can you just ignore lines with |
I do not think we can simply ignore the lines that contains FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base |
Ah okay, so you need to store the labels (base for example) and ignore them? |
I have the same problem! :) |
Dockerfile
with intermediate layer (regression works with 3.3.0
)
Yes, kind of. I need to think about it again, but I believe the following will work. I am not sure if there is a more efficient solution. public sealed class GitHub : List<string>
{
private static readonly Regex FromLinePattern = new Regex("FROM (?<arg>--[^\\s]+\\s)*(?<image>[^\\s]+).*", RegexOptions.None, TimeSpan.FromSeconds(1));
public GitHub()
{
Add("FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build1");
Add("FROM mcr.microsoft.com/dotnet/sdk:7.0 as build2");
Add("FROM mcr.microsoft.com/dotnet/sdk:7.0");
Add("FROM mcr.microsoft.com/dotnet/sdk:6.0");
Add("FROM build1 AS final1");
Add("FROM build1 AS final2");
Add("FROM mcr.microsoft.com/as/AS:5.0");
}
[Fact]
public void Issue972()
{
// TODO: Only process lines that match FromLinePattern.
IEnumerable<string> stages = this
.Select(line => line.Split(new[] { " as ", " AS " }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
.Where(substrings => substrings.Length > 1)
.Select(substrings => substrings[substrings.Length - 1])
.Distinct()
.ToList();
IEnumerable<string> images = this
.Select(line => FromLinePattern.Match(line))
.Where(match => match.Success)
.Select(match => match.Groups["image"])
.Select(group => group.Value)
.Where(value => !stages.Any(stage => stage.EndsWith(value)))
.Distinct()
.ToList();
Assert.Equal(4, stages.Count());
Assert.Equal(4, images.Count());
}
} |
Maybe add |
I am also observing a problem with 3.4.0
The BuildAsync fails now with "invalid tag name" as the $RUNTIME_VERSION is used as a tag instead of being resolved. I suspect this change to be the problem: https://github.com/testcontainers/testcontainers-dotnet/pull/951/files |
Thank you, that is another case we need to address. I might have merged the feature to pull images from private registries to fast 😬. |
No worries, it's a great library and you responded very fast to the problems :) We can use |
Much appreciated. I will address the issue later this week. In the first fix, I will not include the resolution of Dockerfile
|
I have prepared a fix in #979. If anyone would like to review it, your feedback would be appreciated. |
This is still not working with 3.5.0. Getting the same results as OP. Works fine with 3.3.0. My Dockerfile looks like this: ARG DOTNET_RELEASE=7.0
FROM mcr.microsoft.com/dotnet/aspnet:$DOTNET_RELEASE AS base
WORKDIR /app
ENTRYPOINT ["dotnet", "MyApp.dll"]
FROM base AS final
ARG DOTNET_RELEASE=7.0
ARG BUILD_CONFIGURATION=Release
ARG PublishProtocol=publish
COPY bin/$BUILD_CONFIGURATION/net$DOTNET_RELEASE/$PublishProtocol .
# Use unprivileged ports
EXPOSE 9080
ENV ASPNETCORE_URLS=http://+:9080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl --fail http://localhost:9080/health || exit 1
# Use non-root user to run service
RUN groupadd -r service && useradd --no-log-init -r -g service service
RUN chown -R service:service /app
RUN chmod 755 /app
USER service:service |
It is working as described. |
Problem
I cannot give the docker directory to the
ImageFromDockerfileBuilder
, only the dockerfile is possible:I need to set the root to a certain directory so that the Copy instructions in my Dockerfile work.
Solution
I am not sure if this is enough, but consider this:
Add another method accepting the dockerfile and the directory.
Benefit
This change could enable my use case for using the
ImageFromDockerfileBuilder
.Alternatives
I am not sure if there are other alternatives, I don't understand Docker well enough yet.
Would you like to help contributing this enhancement?
Yes
The text was updated successfully, but these errors were encountered: