DOCKERFILE, Attirbutes in it - docker

I dont really understand what is WORKDIR
I have seen many sources by no one says exactyly where is that WORKDIR
I am using Windows
WORKDIR /usr/src/my_app_directory
Here is the sample from one website, it says that my workdir is /usr/src/my_app_directory.
Can I write anything as my workdir if yes where is that workdir?

Put simply it used to change the default working directly of the container e.g. The directory you are logged into when you first connect or start the container.

Related

Share go modules with docker builder stage

[EDIT - added clarity]
Here is my current env setup :
$GOPATH = /home/fzd/go
projectDir = /home/fzd/go/src/github.com/fzd/amazingo
amazingo has a go.mod file that lists several (let's say thousands) dependencies.
So far, I used to go build -t bin/amazingo cmd/main.go, but I want to share this with other people and have a build command that is environment-independent. Using go build has the advantage of downloading each dependency once -- and then using those in ${GOPATH}/pkg/mod, which saves time and bandwidth.
I want to build in a multistage docker image, so I go with
> cat /home/fzd/go/src/github.com/fzd/amazingo/Dockerfile
FROM golang:1.17 as builder
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /bin/amazingo cmd/main.go
FROM alpine:latest
COPY --from=builder /bin/amazingo /amazingo
ENTRYPOINT ["/amazingo"]
As you can expect it, the builder is "naked" when I start it, so it has to download all my dependencies when I docker build -t amazingo:0.0.1 . . But it will do so everytime I call it, which can be several times a day.
Fortunately, I already have most of these dependencies on my disk. I would be happy to share these files (that are located in my $GOPATH/pkg/mod) with the builder, and help it build faster on my machine.
So the question is: how can I share my ${GOPATH} (or ${GOPATH}/mod/pkg) with the builder ?
I tried adding the following to the builder
ARG SRC_GOPATH
COPY ${SRC_GOPATH} /go
and call docker build --build-arg SRC_GOPATH=${GOPATH} -o amazingo:0.0.1 ., but it wasn't good enough - I got an error (COPY failed: file not found in build context or excluded by .dockerignore: stat home/fzd/go: file does not exist)
I hope this update brings a bit more clarity to the problem.
=======
I have a project with a go.mod file.
I want to build that project using a multistage docker image.
(this article is a perfect example)
The issue is that I have "lots" of dependencies, and each of them will be downloaded inside my Docker builder stage.
Is there a way to "share" my GOPATH/pkg/mod with the docker build... command (in some ways, having a local cache) ?
Your end goal isn't completely clear, but the way that I use a multistage build would look something like this for a (dirt-simple) go app, assuming that you ultimately want the docker container to run your go app. You will need to get your source into the build container somehow as well - that is not shown here:
FROM golang:1.17.2-alpine3.14 as builder
WORKDIR /my/app/source/dir
RUN go get && go build -o /path/to/my/app/binary
FROM alpine3.14 AS release
# install runtime deps, if any
# create necessary files and folders, if any
COPY --from=builder /path/to/my/app/binary /usr/local/bin
ENTRYPOINT /usr/local/bin/binary --options
In this way, the source of your application and all dependencies will not be present in the released image, only the compiled binary.
Of course you don't have to specify an output path for that, I think it just makes it a little clearer in this example. And of course you can use whatever base image/images you want to - I'm treating this as though you don't need the go runtime on your release image.

Can someone explain what does 5th line mean . i.e ADD . $HOME_DIR mean in docker file?

I have a problem with 5th line of my Dockerfile. I couldn't figure out what that means.
FROM python:3.7-alpine
LABEL author= APPLE
LABEL company= PINEAPPLE
ARG HOME_DIR='/schooldata'
ADD . $HOME_DIRECT ##[ this line ]
EXPOSE 5000
WORKDIR $HOME_DIRECT
RUN pip install -r requirements.txt
ENTRYPOINT ["python", "app.py"]
Here :
ADD . $HOME_DIRECT
ADD performs a resource copy from a source to the current built image with the following specificity : if that is recognized as an archive (tar,zip...), it copies its content, otherwise it copies the contained files/directories such as.
The two next arguments are the source resource and the target resource of ADD.
. means that the source is the build context. Build context is the last argument of the docker build command : often we specify . such as docker build FooTag . to represent the current directory where the docker build command is executed but that may be different.
$HOME_DIRECT is the target directory of the copy inside the built image.
As a side note, ADD has a quite complex behavior (it also may accept URL as source, so it should be favored over COPY only for special cases (URL and copy archive's content).
In most of cases that is indeed better :
COPY . $HOME_DIRECT
It will add the content of your working directory (where the build command has been executed) into you image in the location defined in environment variable HOME_DIRECT
More details: here

Using Dockerfile ARG within an ADD statement

I am trying to create a dockerfile that adds files from build directory to the working directory.
The build directory can vary and thus needs to be specified by an argument:
ARG BUILD_SOURCE
FROM node:8.11.4
WORKDIR /usr/local/app
ADD "$BUILD_SOURCE" .
I ran this with docker build BUILD_SOURCE=bin/bundle ..
Somehow the ARG is not substituted so that the whole current directory is added to the image.
When I hardcode the build source it works fine.
I have tried using ENV instead, copying the arg into the the env like this:
ENV BUILD_SOURCE $BUILD_SOURCE
ADD "${BUILD_SOURCE}" .
That didn't work either.
In the official docker documentation I cannot find this behaviour being mentioned.
Does anybody why this is happening and what possible workaround would be?
Ok, I figured it out.
The ARG must be placed below the FROM statement unless it is used within the FROM statement:
FROM node:8.11.4
ARG BUILD_SOURCE
WORKDIR /usr/local/app
ADD "$BUILD_SOURCE" .

docker add "requires at least one argument" error

I have a folder which contains all the necessary components for an app, which I want to make a container of. I have everything set up so far, with the directory /home/user/Documents/App in the Dockerfile under the ADD heading. Then when Idocker build . in the App directory I get this
ADD /home/user/Documents/App
ADD requires at least one argument
I realize that this is probably a simple fix but I am new to this so any help would be greatly appreciated. Thank you
FROM alpine
ADD </home/user/Documents/App> </home/user/Documents/DockerApp>
WORKDIR /code
RUN pip install -r requirements.txt
EXPPOSE 8080
CMD ["python", "app.py"]
You need a source and destination for the ADD command. The source here is the app folder path. The destination should be where you want the dockerfile is run.
Try this I think it might work
ADD defined in Dockerfile has the following structure
ADD sourceJarName destinationJarName
e.g.
ADD target/spring-boot-rest-docker-example-0.0.1-SNAPSHOT.jar app.jar
change your ADD likewise and try it will work

I'm trying to make the perfect docker build file, do i need to build it from scratch each time?

For an assignment the marker requires of me to create a dockerfile to build my project's container, however I have a fairly complex set of tasks I need to have work in the right way together for my dockerfile to be of any use to me, so I am currently building a file that takes 30 minutes each time just to see if minor changes affect the outcome in the right way, so my question is, is there a better way of doing this?
The Dockerfile best practices, or an earlier question might help: Creating a Dockerfile - docker starts from scratch on each new build
In my experience, a full build every time means you're working against docker's caching mechanism, usually by having COPY . . early in the Dockerfile.
If the files copied into the image are then used to drive a package manager, or download other sources - try copying just the script or requirements file, then using it, then copying the rest of the sources.
a simplified python example, restated from the best practices link:
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
With that structure, as long as requirements.txt does not change, the first COPY and following RUN command use cached layers and rebuilds are much faster.
The first tip is using COPY/ADD for artifacts that need to be download when docker builds.
The second tip is, you can create one Dockerfile for each step and reuse them in next steps.
for example, if you want to install postgres db, and install wildfly in your image. You can start creating a Dockerfile for postgresDB only, and build it to make your-postgres docker image.
Then create another Dockerfile which reuse your-postgres image by
FROM your-postgres
.....
and so on...

Resources