Hello i am trying to recreate inside a docker image my host folder that contains:
Publish (folder containing a .NET app )
dockerfile
conf.json
dockerfile
FROM microsoft/aspnetcore
WORKDIR /app
ADD . /app
ENTRYPOINT ["dotnet","/publish/Bench.dll"]
EXPOSE 8300
When i am trying to see what it created using docker exec -it <id> bash it just takes all the content of publish and throws it inside app without copying conf.json.
I have also tried with
COPY . /app,
COPY /publish /app+COPY conf.json /app to no avail.
Whatever i am trying it won't copy the folder as-is and it wont put the json file beside it.
What am i doing wrong?
So I tested this out. I had the publish folder dockerfile and conf.json in the same directory where I build the image from. That is the key. Here I am using nginx as my base image. The following is the command I used to build the nginx image
docker build -t test/nginx .
and the dockerfile is as below. So I create the app directory by using the RUN command. You will have to use the similar command in .net to create that directory if it doesn't exist. Also pay attention to the docker build logs. It will tell you things that are important. Also you could add an ls command in the dockerfile to list the files in the folder /app if you want to.
FROM nginx
RUN mkdir /app
WORKDIR /app
ADD . /app
After I create a container from the image I built, i can navigate to /app folder and view my
Dockerfile, config.json and publish folder in there. Hope this helps
Let me know if you have any questions
Related
I have a Dockerfile and I want to add/copy a file.txt from my Desktop. How can I do?
This is my docker file:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build-env
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim
WORKDIR /app
COPY --from=build-env /app/out ./
# COPY ...
RUN useradd -ms /bin/bash moduleuser
USER moduleuser
ENTRYPOINT ["dotnet", "csharpexamplemodule.dll"]```
Short answer: You don't (see Adding files from outside context).
As far as copying (COPY / ADD) goes the file you want to copy to the container needs to be in the same context. Context in this case is the directory of your dockerfile or one of it's subdirectories. Assuming your dockerfile is not on the desktop as well, you are left with 2 options.
Copy the file from your desktop to the context that docker gets, as mentioned above
If you don't need the file during the build stage but still within your container, you can use docker mount (docker mount docs).
if you check the docker documentation of the copy command, you should see the following:
https://docs.docker.com/engine/reference/builder/#copy
COPY obeys the following rules:
The <src> path must be inside the context of the build;
you cannot COPY ../something /something, because the first
step of a docker build is to send the context directory
(and subdirectories) to the docker daemon.
So I would suggest you copy the file from your desktop to your docker context (where you run the docker command from). Or to create a symbolic link.
PS: It is a good practice to avoid using ADD if you don't need the tar and remote URL handling.
My directory is:
-Dockerfile
app/
-main.go
media/
/css
/html
/img
/svg
Inside the html folder, I have subfolders to organise my HTML files, so the path to the HTML files is media/html/*/*.html
And I have my Dockerfile as follows:
FROM golang:alpine
# Set necessary environmet variables needed for our image
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
# Copy the code into the container
COPY media .
# Move to working directory /build
WORKDIR /build
# Copy the code from /app to the build folder into the container
COPY app .
# Configure the build (go.mod and go.sum are already copied with prior step)
RUN go mod download
# Build the application
RUN go build -o main .
WORKDIR /app
# Copy binary from build to main folder
RUN cp /build/main .
# Export necessary port
EXPOSE 8080
# Command to run when starting the container
CMD ["/app/main"]
and my main.go is:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// We create the instance for Gin
r := gin.Default()
// Path to the static files. /static is rendered in the HTML and /media is the link to the path to the images, svg, css.. the static files
r.StaticFS("/static", http.Dir("../media"))
// Path to the HTML templates. * is a wildcard
r.LoadHTMLGlob("../media/html/*/*.html")
r.NoRoute(renderHome)
// This get executed when the users gets into our website in the home domain ("/")
r.GET("/", renderHome)
r.Run(":8080")
}
func renderHome(c *gin.Context) {
c.HTML(http.StatusOK, "my-html.html", gin.H{})
}
Problem is, I can run without problem my app in Golang with go run main.go, I can build the Docker image without problems, but on the moment to run a Docker container from the image, I got the error:
panic: html/template: pattern matches no files: ../media/html/*/*.html
The path is correct (since is also proven because I can run it in plain go) and it seems that Docker is not coping the files correctly, or at least not in the right directory. What is failing? The full simple project can be found here
media is a bad choice for a Docker folder, because a typical Linux container already has a /media folder.
But that's not the root cause.
The root cause is that COPY media . copies the contents of media folder to /. You probably want COPY media/ /media/ if you want to preserve the media folder itself (or use WORKDIR /media).
As a debug tool, you can run your container with a shell as entrypoint to "look around" it without starting your app:
docker build . -t test
docker run -it --rm test sh
/app # ls /media
cdrom floppy usb
/app # ls -R /html
/html:
website
/html/website:
my-html.html
As you can see your media/html folder is located at /html.
Some more notes:
It's a good idea to move go mod download to before COPY app so that the downloaded modules can be cached:
FROM golang:alpine
WORKDIR /build
COPY app/go.mod app/go.sum ./
RUN go mod download
COPY app .
RUN go build -o main .
WORKDIR /app
RUN cp /build/main .
COPY media /media/
EXPOSE 8080
CMD ["/app/main"]
As a next step you can look into two-stage builds to not depend on the golang image for running the compiled app (is only needed for building really).
I'm trying to put a dockerfile in a subdirectory of my main startup project AppMain. AppMain has a dependency project called AppDependency. When the dockerfile is in the root directory of AppMain, all works correctly, but when it's nested in a subdirectory of the AppMain, it fails with
4>Step 5/20 : COPY ["AppMain/AppMain.csproj", "AppMain/"]
4>COPY failed: stat /var/lib/docker/tmp/docker-builder453314675/AppMain/AppMain.csproj: no such file or directory
So that makes sense to me since it's nested in a subdirectory, so I simply added a "../" in front of the COPY commands but that results in the following context exception:
4>COPY failed: Forbidden path outside the build context: ../AppMain/AppMain.csproj ()
Alright so that makes sense as well because the docker documentation states that the context starts where the dockerfile is located, but this leads me to ask the real question.
If it cannot copy outside of the where the dockerfile is located and it works when its located in the root of AppMain, then why doesn't it fail when copying the AppReference project which obviously is above where the docker file is located and outside the context since it would have to go up one directory and then down to the AppReference project?
Is there a way to achieve having a dockerfile nested in a subdirectory?
The entire docker file is listed below.
FROM mcr.microsoft.com/dotnet/core/runtime:2.2-stretch-slim AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["AppMain/AppMain.csproj", "AppMain/"]
COPY ["AppReference/AppReference.csproj", "AppReference/"]
RUN dotnet restore "AppMain/AppMain.csproj"
COPY . .
WORKDIR "/src/AppMain"
RUN dotnet build "AppMain.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "AppMain.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "AppMain.dll"]
When use docker build -t xxx . to build in the subdirectory, only the contents in . will submit to docker daemon for docker build. The things in parent folder will not be able to submit to docker engine to build.
So, you need to move the execution directory back to the parent folder with cd .., then use next to build, it will then send the . which now is the contents of parent folder to engine(But you need now specify dockerfile, like this)
docker build -t xxx -f ./YOUR_Subdirectory/Dockerfile .
It is really working.
What it is ?
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
In the docker docs getting started tutorial part 2, it has one make a Dockerfile. It instructs to add the following lines:
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
What is /app, and why is this a necessary step?
There are two important directories when building a docker image:
the build context directory.
the WORKDIR directory.
Build context directory
It's the directory on the host machine where docker will get the files to build the image. It is passed to the docker build command as the last argument. (Instead of a PATH on the host machine it can be a URL). Simple example:
docker build -t myimage .
Here the current dir (.) is the build context dir. In this case, docker build will use Dockerfile located in that dir. All files from that dir will be visible to docker build.
The build context dir is not necessarily where the Dockerfile is located. Dockerfile location defaults to current dir and is otherwise indicated by the -f otpion. Example:
docker build -t myimage -f ./rest-adapter/docker/Dockerfile ./rest-adapter
Here build context dir is ./rest-adapter, a subdirectory of where you call docker build; the Dokerfile location is indicated by -f.
WORKDIR
It's a directory inside your container image that can be set with the WORKDIR instruction in the Dockerfile. It is optional (default is /, but base image might have set it), but considered a good practice. Subsequent instructions in the Dockerfile, such as RUN, CMD and ENTRYPOINT will operate in this dir. As for COPY and ADD, they use both...
COPY and ADD use both dirs
These two commands have <src> and <dest>.
<src> is relative to the build context directory.
<dest> is relative to the WORKDIR directory.
For example, if your Dockerfile contains...
WORKDIR /myapp
COPY . .
then the contents of your build context directory will be copied to the /myapp dir inside your docker image.
WORKDIR is a good practice because you can set a directory as the main directory, then you can work on it using COPY, ENTRYPOINT, CMD commands, because them will execute pointing to this PATH.
Docker documentation: https://docs.docker.com/engine/reference/builder/
The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction.
The WORKDIR instruction can be used multiple times in a Dockerfile. If a relative path is provided, it will be relative to the path of the previous WORKDIR instruction.
Dockerfile Example:
FROM node:alpine
WORKDIR '/app'
COPY ./package.json ./
RUN npm install
COPY . .
CMD ["npm", "run", "start"]
A alpine node.js was created and the workdir is /app, then al files are copied them into /app
Finally npm run start command is running into /app folder inside the container.
You should exec the following command in the case you have sh or bash tty:
docker exec -it <container-id> sh
or
docker exec -it <container-id> bash
After that you can do ls command and you will can see the WORKDIR folder.
I hope it may help you
You need to declare a working directory and move your code into it, because your code has to live somewhere. Otherwise your code wouldn't be present and your app wouldn't run. Then when commands like RUN, CMD, ENTRYPOINT, COPY, and ADD are used, they are executed in the context of WORKDIR.
/app is an arbitrary choice of working directory. You could use anything you like (foo, bar, or baz), but app is nice since it's self-descriptive and commonly used.
Basically I created an asp.net mvc project. I added a Dockerfile in the project folder.
FROM microsoft/aspnet:1.0.0-rc1-update1
ADD . /app
WORKDIR /app/approot
EXPOSE 5004
ENTRYPOINT ["./web"]
Now I open Docker Quickstart Terminal on my Windows desktop. Running the command
docker build -t hellodocker:0.1.0 .
See the result
However I can't find the image when I run it.
So what is wrong?
EDIT
Thanks for the comment, I correct the typo. But there is an another error.
EDIT-1
If I change the ENTRYPOINT as ENTRYPOINT ["dnx", "-p", "project.json", "web"]
Then I get another error:
Unable to reslolve project from /app/approot
EDIT-2
The context in the directory is as:
Your project is being added to the image as /app. So, in the container, the project.json lives at /app/project.json. But your WORKDIR is set to /app/approot.
This effectively makes your ENTRYPOINT looking for project.json at /app/approot, which it does not exist. You'll either need to change WORKDIR to /app or COPY . /app/approot.