The most basic docker build fails on COPY - docker

I'm trying to build a docker image for this first time out of the exeutables for a VS project that is already compiled. I do not want docker to build my project (oh no given the problems I already have). As a result I have the following Dockerfile in the folder where my app source files (and compiled binaries) are:
Location: d:\MyApp
Dockerfile Contents:
FROM microsoft/windowsservercore
COPY bin /app
ENTRYPOINT ["C:\\app\\x86\\Debug\\MyApp.exe"]
Contents of MyApp folder:
MyApp\
MyApp\bin
MyApp\bin\x64
MyApp\bin\x64\Release
MyApp\bin\x64\Debug
MyApp\bin\x64\Release\* (lots of binaries)
MyApp\bin\x64\Debug\* (lots of binaries)
...
MyApp\Dockerfile
Command window:
d:\MyApp> docker image build .
Sending build context to Docker daemon 3.584kB
Step 1/3 : FROM microsoft/windowsservercore ---> 4dba31379dad
Step 2/3 : COPY bin /app COPY failed: CreateFile \\?\C:\ProgramData\Docker\tmp\docker-builder196938557\bin: The system cannot find the file specified.
If I change the COPY line to COPY ./bin/*.* /app/ :
Sending build context to Docker daemon 3.584kB
Step 1/3 : FROM microsoft/windowsservercore
---> 4dba31379dad
Step 2/3 : COPY ./bin/*.* /app/
COPY failed: no source files were specified

Somehow I had a ".dockerignore" with a "*" in it. After removing that line everything seems to be ok.

Related

Multiple Dockerfiles re-using shared library in project

I have the following code structure and I am trying to structure my Dockerfile(s) as to maximize caching and the like.
serverfoo/
Dockerfile
main.go
serverbar/
Dockerfile
main.go
proto/
Dockerfile
sharedproto.proto // Generates a sharedproto.pb.go file to be imported.
Both serverfoo and serverbar import the compiled sharedproto.pb.go file which I manually regenerate on my workstation. This works fine but now I am attempting to containerize my two servers.
The Dockerfiles with my server folders cannot (by default) copy proto/ content. Ideally I pre-compile the protobufs into a sharedproto.pb.go then import a cached version of that file into the two server Dockerfiles. The goal is to cache the compiled protobufs until the underlying protos are modified.
I am new to Docker and need some best practice for this type of thing. I want to avoid a root Dockerfile in my project's directory that just has code to compile a zillion different servers.
I am open to restructuring my project to some degree.
NOTE: I suppose your target is to have on the specific server
container both the compiled go file ( from specific main.go file )
and the compiled protocol buffer file ( from shared
sharedproto.proto file ).
Assuming your files are organized as follow on your workstation:
serverfoo/
Dockerfile
main.go
serverbar/
Dockerfile
main.go
proto/
Dockerfile
sharedproto.proto
You can structure the specific server Dockerfile using the multistage build as follow ( e.g. serverbar Dockerfile ):
#####
# The serverbar Dockerfile
#####
#----
# Compile proto stage
#----
FROM moul/protoc-gen-gotemplate AS protostage
WORKDIR /workspace
# Copy .proto file
COPY proto/sharedproto.proto .
# Compile .pb.go
RUN protoc -I=. --go_out=. sharedproto.proto
#----
# Build stage
#----
FROM golang:1.12.4-alpine3.9 as buildstage
WORKDIR /workspace
COPY serverbar/main.go .
RUN GOOS=linux GOARCH=amd64 go build -o serverbar main.go
#----
# Final stage
#----
FROM alpine:3.7
WORKDIR /home
COPY --from=buildstage workspace/serverbar .
COPY --from=protostage workspace/sharedproto.pb.go .
CMD ["./serverbar"]
Using this approach you basically have the following 3 stages:
proto stage: On the container created on this stage you need to compile the shared protocol buffer source file into the sharedproto.pb.go that then will be included on the third final stage. So here you would need to install on the container the protoc compiler and the related Go plugin. However, as usual with Docker, you'll find a docker image that already includes your needed tools. For this purpose we can start from the moul/protoc-gen-gotemplate docker image.
Specifically the follow Dockerfile instruction generates the workspace/sharedproto.pb.go:
RUN protoc -I=. --go_out=. sharedproto.proto
build stage: Here you need to compile the server source file into the executable one. Also this will be included on the third final stage. To avoid to install Golang we can start from the golang:1.12.4-alpine3.9 docker image that already includes all the needed tools.
Specifically the follow Dockerfile instruction generates the workspace/serverbar executable:
RUN GOOS=linux GOARCH=amd64 go build -o serverbar main.go
final stage: This is the server container that we'll then upload on our Docker registry for test or production where we'll copy the files compiled on the previous two stage with the following commands:
COPY --from=buildstage workspace/serverbar .
COPY --from=protostage workspace/sharedproto.pb.go .
One of the advantages of this solution is that, for each server build, you can cache the compiled protobufs until the underlying protos are modified.
Example:
Building first time the serverbar container we can note that .proto compilation is performed on a new container with id 92ae211bd27d:
> docker build -f serverbar/Dockerfile .
Sending build context to Docker daemon 10.24kB
Step 1/13 : FROM moul/protoc-gen-gotemplate AS protostage
---> 635345fde953
Step 2/13 : WORKDIR /workspace
---> Using cache
---> de8890a5e775
Step 3/13 : COPY proto/sharedproto.proto .
---> 1253fa0576aa
Step 4/13 : RUN protoc -I=. --go_out=. sharedproto.proto
---> Running in 8426f5810b98
Removing intermediate container 8426f5810b98
---> 92ae211bd27d <=========================================
Step 5/13 : FROM golang:1.12.4-alpine3.9 as buildstage
---> b97a72b8e97d
Step 6/13 : WORKDIR /workspace
....
Building then a second time without modifying the sharedproto.proto we can note that container with id 92ae211bd27d is re-used from cache.
> docker build -f serverbar/Dockerfile .
Sending build context to Docker daemon 10.24kB
Step 1/13 : FROM moul/protoc-gen-gotemplate AS protostage
---> 635345fde953
Step 2/13 : WORKDIR /workspace
---> Using cache
---> de8890a5e775
Step 3/13 : COPY proto/sharedproto.proto .
---> Using cache
---> 1253fa0576aa
Step 4/13 : RUN protoc -I=. --go_out=. sharedproto.proto
---> Using cache <=========================================
---> 92ae211bd27d
Step 5/13 : FROM golang:1.12.4-alpine3.9 as buildstage
---> b97a72b8e97d
....

Docker - No executable found matching command "dotnet-/bin/MyApp.dll"

I'm learning Docker. I have a Console app created with .NET Core. This console app has a Dockerfile in it. That Dockerfile looks like this:
FROM microsoft/dotnet:2.1-runtime AS base
FROM microsoft/dotnet:2.1-sdk
# Copy the compiled files
COPY . ./bin
ENTRYPOINT ["dotnet", "/bin/MyApp.dll"]
I intentionally want to copy the compiled files into the Docker images. I do NOT want to build the code on the Docker image due to issues with the dependencies. Still, when I select the play button in Visual Studio that says "Docker" I can see that the image gets successfully created via the "Output" window. In addition, my console app writes messages to the "Output" window as expected. For these reasons, I'm assuming my Dockerfile is correct.
Now, I try to run the build image from a command line outside of Visual Studio. From the directory where my .csproj file is located, I run docker build .. When I do this, I see the following:
Sending build context to Docker daemon 11.8MB
Step 1/4 : FROM microsoft/dotnet:2.1-runtime AS base
---> 59184f8be664
---> Using cache
---> 3a64d221c7f1
Step 2/4 : FROM microsoft/dotnet:2.1-sdk
---> 6691c7a1e6c7
Step 3/4 : COPY . ./app
---> e3e894ef7997
Step 4/4 : ENTRYPOINT ["dotnet", "/bin/MyApp.dll"]
---> Running in 355713fb3562
Removing intermediate container 355713fb3562
---> 88d4918847b9
Successfully built 78d4918847b8
I then run docker container run 78d4918847b8 from the command line and I see the message:
No executable found matching command "dotnet-/bin/MyApp.dll"
I don't understand why I can run the image from Visual Studio but not from the command line myself. What am I doing wrong?
The error message actually means File not found (see https://github.com/dotnet/core-setup/issues/1126 as suggested by #oneturkmen).
The reason the file is not found is because you are copying the files to ./bin which is a relative path but the ENTRYPOINT is looking in /bin which is an absolute path, related to the root folder.
If you change your DOCKERFILE to:
FROM microsoft/dotnet:2.1-runtime AS base
FROM microsoft/dotnet:2.1-sdk
# Copy the compiled files
COPY . ./bin
ENTRYPOINT ["dotnet", "./bin/MyApp.dll"]
then it should work. Please note the ./bin in the entrypoint

No such file or directory, when building scala docker image

I have auto generated the following docker file with sbt for my scala project:
FROM robsonoduarte/8-jre-alpine-bash:latest
WORKDIR /opt/docker
ADD opt /opt
RUN ["chown", "-R", "daemon:daemon", "."]
EXPOSE 6999
USER daemon
ENTRYPOINT ["bin/app"]
CMD []
Yet when I run build . -t app I get the following error:
Sending build context to Docker daemon 166.2MB
Step 1/7 : FROM robsonoduarte/8-jre-alpine-bash:latest
---> 9bbc00a23a9b
Step 2/7 : WORKDIR /opt/docker
Removing intermediate container 817f86d4a46e
---> b648d213f308
Step 3/7 : ADD opt /opt
ADD failed: stat /var/lib/docker/tmp/docker-builder679116314/opt: no such file or directory
I have tried to reinstall docker as suggested in another SO answer, but that did not help. I am also using windows, and I cannot find the /var/lib folder.
The ADD command copies files from <src> to <dest>. In your case, Docker expects a folder called 'opt' from the location where you run build . -t app. Does such a folder exist?

Docker: COPY failed: CreateFile, looking for file in strange location

Trying to follow the tutorial found here, but running into problems.
I run the following command from my project dir:
docker build -t my.solution .
I get the following:
Sending build context to Docker daemon 111.6kB
Step 1/17 : FROM microsoft/aspnetcore:2.0-nanoserver-1709 AS base
---> ccfb41c8f5b5
Step 2/17 : WORKDIR /app
---> Using cache
---> e29a68e16001
Step 3/17 : EXPOSE 80
---> Using cache
---> 976388139964
Step 4/17 : FROM microsoft/aspnetcore-build:2.0-nanoserver-1709 AS build
---> d7ab4e860769
Step 5/17 : WORKDIR /src
---> Using cache
---> 4ab01220723e
Step 6/17 : COPY my.solution.sln ./
COPY failed: CreateFile \\?\C:\ProgramData\Docker\tmp\docker-builder564035917\my.solution.sln: The system cannot find the file specified.
I don't know why it's trying to find the file in the location it's looking for it. Can anyone help me? Is there a config setting I need to make? My Docker file looks like this:
FROM microsoft/aspnetcore:2.0-nanoserver-1709 AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/aspnetcore-build:2.0-nanoserver-1709 AS build
WORKDIR /src
COPY my.solution.sln ./
COPY my.solution/my.solution.csproj my.solution/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/my.solution
RUN dotnet build -c Release -o /app
FROM build AS publish
RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "my.solution.dll"]
UPDATE
Per #AlexGera's answer, I tried changing my docker file to:
FROM microsoft/aspnetcore:2.0-nanoserver-1709 AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/aspnetcore-build:2.0-nanoserver-1709 AS build
WORKDIR /src
VOLUME C:/tmp
COPY my.solution.sln c:/tmp/
COPY my.solution/my.solution.csproj my.solution/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/my.solution
RUN dotnet build -c Release -o /app
FROM build AS publish
RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "my.solution.dll"]
but the error message doesn't change significantly:
docker build -t my.solution .
Sending build context to Docker daemon 111.6kB
Step 1/18 : FROM microsoft/aspnetcore:2.0-nanoserver-1709 AS base
---> ccfb41c8f5b5
Step 2/18 : WORKDIR /app
---> Using cache
---> e29a68e16001
Step 3/18 : EXPOSE 80
---> Using cache
---> 976388139964
Step 4/18 : FROM microsoft/aspnetcore-build:2.0-nanoserver-1709 AS build
---> d7ab4e860769
Step 5/18 : WORKDIR /src
Removing intermediate container 31e30e2346aa
---> 61c7df20f3c4
Step 6/18 : VOLUME C:/tmp
---> Running in fada6c728151
Removing intermediate container fada6c728151
---> 7a650440cc1f
Step 7/18 : COPY my.solution.sln c:/tmp/
COPY failed: CreateFile \\?\C:\ProgramData\Docker\tmp\docker-builder832533802\my.solution.sln: The system cannot find the file specified.
Seems to me the standard Dockerfile that comes with a new solution is bugged :/
I moved the Dockerfile up to the solution folder, from PowerShell:
mv Dockerfile ../Dockerfile
Running the docker build command from there did the trick for me...
The COPY command will copy the file from the build context, or a previous build stage if you specify the stage. With your build command:
docker build -t my.solution .
The context is . which is first sent to the docker engine which places that in a temporary location just for the build.
Therefore with your copy command:
Step 6/17 : COPY my.solution.sln ./
The file my.solution.sln needs to exist in the folder where the build command was run.
For the destination, the file will be copied to the working directory inside the container, or /src in your example.
This was probably caused by the .dockerignore file next to you DockerFile, ignoring everything but /obj/*.
Once you copied it to another folder you didn't copy the .dockerignore file, so nothing was excluded and it worked.
Before copying add a volume in your image to copy where to.
Something like this:
VOLUME C:/Users/mysolution
COPY my.solution.sln C:/Users/mysolution
Try not to use dots for directory names.
I found that same situation in a VS2017 Solution where the build is started by docker compose and yml files one directory above the project.
If you want to build by docker build with the docker file directly, you need to move the docker file one level above the context
Use the \\
FROM microsoft\\aspnetcore-build:2.0-nanoserver-1709 AS build
see the below example
FROM microsoft/aspnetcore:2
WORKDIR /app
EXPOSE 80
COPY bin\\Debug\\netcoreapp2.0 .
ENTRYPOINT ["dotnet","DOCKER-API.dll"]
I move my Dockerfile to the root folder (where exists .sln and .dockerignore files) and my problem was resolved
Perfect suits for who uses visual studio :
run this command :
docker build -t . your_application_name/Dockerfile
Dockerfile Copy path :
["your_application_name/your_application_name.csproj","your_application_name/"]
we run the build command docker build command it is unable to find the dockerfile in the project path location.
Visual Studio creates the Docker file at Project level, however, the Dockerfile is tailored to be run from an upper level (Solution level).
The easiest way to fix this problem is to go one level up (Solution folder), and specify the project folder:
docker build --tag tagone -f Project/Dockerfile .

Docker compose build error - Project file does not exist

I'm trying to create docker compose which run my ASP.NET Core app and mssql, but I'm getting an error during build.
Here's my docker compose file:
# Build Stage
FROM microsoft/aspnetcore-build:latest as build-env
WORKDIR /source
COPY . .
RUN dotnet restore ./Travelingowe.sln
RUN dotnet publish --output ${source:-obj/Docker/publish} --configuration Release
# Publish Stage
FROM microsoft/aspnetcore:latest
COPY --from=build-env ./obj/Docker/publish /app
WORKDIR /app
ENTRYPOINT ["dotnet", "Api.dll"]
when I run in CMD -> docker-compose up I'm getting:
Building api
Step 1/9 : FROM microsoft/aspnetcore-build:latest as build-env
---> d6273f7c44d4
Step 2/9 : WORKDIR /source
---> Using cache
---> 978f1c31e14a
Step 3/9 : COPY . .
---> Using cache
---> bcc750adcb99
Step 4/9 : RUN dotnet restore ./Travelingowe.sln
---> Running in 764199859de4
MSBUILD : error MSB1009: Project file does not exist.
Switch: ./Travelingowe.sln
ERROR: Service 'api' failed to build: The command '/bin/sh -c dotnet restore ./Travelingowe.sln' returned a non-zero code: 1
Do you have any ide what is wrong?
Thanks!
UPDATE:
My project files:
you have issues with your working directory try using absolute path instead of relative path in your working directory in docker file
TL;DR
Put your Dockerfile in your project root folder.
There are several question you need to think of:
Where is your Dockerfile?
How does docker-compose.yaml point to Dockerfile?
It seems like you put your Dockerfile in the other folder.
As document mentions:
Compose uses an alternate file to build with. A build path must also be specified.
When you use the Dockerfile on different folder with docker-compose.yaml you have to set up the context property.
As it set up, it will consider the Dockerfile's folder as project root folder. So when the command dotnet restore ./Travelingowe.sln executed, it shows you the error
You can manually test the command by running dotnet restore ./Travelingowe.sln in Dockerfile's folder. It should show the detail error message.

Resources