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
Related
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
....
i would like to build my first Docker image, containing Apache Tomcat and a deployed web app. My Dockerfile is really small, based on Tomcat:8.0 image and is supposed to copy a WAR file into Tomcat's appBase.
Build of the image reports success, but the file is nowhere to be found in the container.
Copying from host to the container work w/o issues using "docker cp":
[root#edubox dock]# docker cp jdbcdemo_3.war 15dd44bbf992:/usr/local/tomcat/webapps/
My Dockerfile:
# we are extending everything from tomcat:8.0 image ...
FROM tomcat:8.0
MAINTAINER simo
# COPY path-to-your-application-war path-to-webapps-in-docker-tomcat
COPY ./jdbcdemo_3.war /usr/local/tomcat/webapps/
EXPOSE 8082
Image build:
root#edubox dock]# docker image build -t simo/jdbcdemo_3 --tag=recent ./
Sending build context to Docker daemon 10.24 kB
Step 1/4 : FROM tomcat:8.0
---> ef6a7c98d192
Step 2/4 : MAINTAINER simo
---> Using cache
---> 54d824d7258b
Step 3/4 : COPY ./jdbcdemo_3.war /usr/local/tomcat/webapps/
---> Using cache
---> f94330423a93
Step 4/4 : EXPOSE 8082
---> Running in 74b6dd0364b2
---> 9464f11ac18e
Removing intermediate container 74b6dd0364b2
Successfully built 9464f11ac18e
I would expect COPY to place the file where specified or an error message because of which this does not work.
Please try this way,
Keep the "jdbcdemo_3.war" where your Dockerfile exists. And make this change in the Dockerfile.
(remove ./ from your Dockerfile) like,
COPY jdbcdemo_3.war /usr/local/tomcat/webapps/
please check the permission side of the file.
you can give full permission and test once. (user:group)
try this: COPY jdbcdemo_3.war /tmp
In your Dockerfile. And build the image and check in the /tmp directory. If the file copied successfully, give the permission to /usr/local/tomcat/webapps/ Or copy to /tmp first and then copy from /tmp to /usr/local/tomcat/webapps/. Using COPY command in Dockerfile
Hi and many thanks for offering advice. The issue has been trivial in the end. I have not been examining the correct container.
I did not realize one needs to pick the freshly created image, run the container with this image and only afterwards peek for changes described in the Dockerfile in that container.
I have been looking into parent container which i now understand could not have worked.
Sry for wasting your time ;-)
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.
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.
All, i'm trying to persistently copy files from my host to an image so those files are available with every container launched based on that image. Running on debian wheezy 64bit as virtualbox guest.
the Dockerfile is fairly simple (installing octave image):
FROM debian:jessie
MAINTAINER GG_Python <[redacted]#gmail.com>
RUN apt-get update
RUN apt-get update
RUN apt-get install -y octave octave-image octave-missing-functions octave-nan octave-statistics
RUN mkdir /octave
RUN mkdir /octave/libs
RUN mkdir /octave/libs/jsonlab
COPY ~/octave/jsonlab/loadjson.m /octave/libs/jsonlab/.
I'm getting the following trace after issuing a build command: docker build -t octave .
Sending build context to Docker daemon 423.9 kB
Sending build context to Docker daemon
Step 0 : FROM debian:jessie
---> 58052b122b60
Step 1 : MAINTAINER GG_Python <[..]#gmail.com>
---> Using cache
---> 90d2dd2f7ee8
Step 2 : RUN apt-get update
---> Using cache
---> 4c72c25cd829
Step 3 : RUN apt-get update
---> Using cache
---> b52f0bcb9f86
Step 4 : RUN apt-get install -y octave octave-image octave-missing-functions octave-nan octave-statistics
---> Using cache
---> f0637ab96d5e
Step 5 : RUN mkdir /octave
---> Using cache
---> a2d278b2819b
Step 6 : RUN mkdir /octave/libs
---> Using cache
---> 65efbbe01c99
Step 7 : RUN mkdir /octave/libs/jsonlab
---> Using cache
---> e41b80901266
Step 8 : COPY ~/octave/jsonlab/loadjson.m /octave/libs/jsonlab/.
INFO[0000] ~/octave/jsonlab/loadjson.m: no such file or directory
Docker absolutely refuses to copy this file from the host into the image. Needless to say a the file loadjson.m is there (cat displays), all my attempts to change the path (relative, absolute, etc.) failed. Any advice why this simple task is problematic?
At the time I originally wrote this, Docker didn’t expand ~ or $HOME. Now it does some expansions inside the build context, but even so they are probably not what you want—they aren’t your home directory outside the context. You need to reference the file explicitly, or package it relative to the Dockerfile itself.
Docker can only copy files from the context, the folder you are minus any file listed in the dockerignore file.
When you run 'docker build' docker tars the context and it sends it to the docker daemon you are connected to. It only lets you copy files inside of the context because the daemon might be a remote machine.
I couldn't get COPY to work until I understood the context (I was trying to copy a file from outside of the context)
The docker build command builds an image from a Dockerfile and a context. The build’s context is the files at a specified location PATH. The PATH is a directory on your local filesystem.
A context is processed recursively. So, a PATH includes any subdirectories.
The build is run by the Docker daemon, not by the CLI. The first thing a build process does is send the entire context (recursively) to the daemon. In most cases, it’s best to start with an empty directory as context and keep your Dockerfile in that directory. Add only the files needed for building the Dockerfile.
Warning: Do not use your root directory, /, as the PATH as it causes the build to transfer the entire contents of your hard drive to the Docker daemon.
Reference:
https://docs.docker.com/engine/reference/builder/#usage
I had similar issue. I solved it by checking two things:
Inside your, docker-compose.yaml check context of the service, docker will not copy any file outside of this directory. For example if the context is app/ then you cannot copy anything from ../app
Check .dockerignore to be sure that you are not ignoring the file you want to copy.
I got it working by first checking what the context was,
setting an absolute path before the source file in
your Dockerfile to get that information:
# grep COPY Dockerfile
COPY /path/to/foo /whatever/path/in/destination/foo
Building with that:
docker build -t bar/foo .
you'll get an error, which states the context-path that Docker
is apparently looking into for its files, e.g.
it turns out to be:
/var/lib/docker/tmp # I don't remember
Copying(!) your set of build-files in that directory (here: /var/lib/docker/tmp),
cd into it, build from there.
See if that works, and don't forget to do some housekeeping cleaning up
the tmp, deleting your files before the next visit(or).
HTH
Michael
Got this error using a Dockerfile for a linux container on a Windows machine:
#24 1.160 Skipping project "/src/Common/MetaData/Metadata.csproj" because it was not found.
Restore worked perfectly on the host machine.
Turned out to be the error mentioned here:
https://stackoverflow.com/a/68592423/3850405
A .csproj file did not match casing in Visual Studio vs the file system.