How to run a Dockerfile locally on a Windows 10 machine? - docker

I'm new to Docker and I'm trying to run a dockerfile locally on my machine to make sure everything is working correctly before uploading it to GitHub and trying it out on another server. Is there a way to do that? I've installed the Docker for Windows 10 and I'm able to navigate to the folder in which the dockerfile exist. When I try to execute the '''docker build -t file_name -f file_name''' I get an error.
I've already downloaded Docker and able to access things correctly. I've tried
'''docker build''' but that doesn't seem to work.
I'm expecting for the dockerfile to run and build successfully. Instead it just errors out during build.

The error has already told you all things:
invalid argument "Dockerfile" for "-t, --tag" flag: invalid reference format: repository name must be lowercase
You could change command to next to have a try:
docker build -t abc -f Dockerfile .
Above, abc is the repo name you tagged for your new image, it should be lowercase as said from the error, meanwhile, the last . need to be added as it will specify the build context.
Example reference to this.

Related

I'm having trouble building dockers

I ran normally from the docker hub to running the image.
But I'm having trouble executing 'build' command.
There appears to be a path problem, but any path given in the current working directory cannot be resolved. Can you give me any advice here?
(I am in wsl2 - ubuntu 20.04)
You don't need to pass the file name to build command, if the file name is Dockerfile just pass the context. use this instead:
docker build -t python-test .

Use console output in Dockerfile

I want to use some console output as the name of my base docker image.
Specifically, I have a chain of dependent docker build files so I am trying to automate this process. So for instance, the Dockerfile of one image derived1 depends on the base image base_image_namein the following scenario:
base_image_name/
Dockerfile
derived1/
Dockerfile
derived2/
Dockerfile
When the base image builds, it grabs its name from its current folder by using ${PWD##*/}. In this case, the base image's folder is called base_image_name, and so the base image is called company:base_image_name.
Then when the derived images build, they should just be able to figure out the base image's name by moving up a directory and looking at that directories name. So for instance, when build the company:derived1 image builds, it should look up one directory, see that it is called base_image_name, and from that infer that it should use the base image company:base_image_name.
I would like to have this structure several layers deep, so I want to automate it. To do that, I have tried several permutations of the syntax
FROM company:$(cd $PWD/../; echo ${PWD##*/})
but I can't seem to get it right. To understand what the command $(cd $PWD/../; echo ${PWD##*/}) is doing, just type it into your terminal..
echo $(cd $PWD/../; echo ${PWD##*/})
simply returns the name of the directory one level up. However, when I try to use this in a Dockerfile, I get the error
Error response from daemon: Dockerfile parse error line 1: FROM requires either one or three arguments
Could somebody please provide me with the correct syntax?
EDIT:
I also tried building the derived images with a build-arg, but that doesn't seem to work either:
build.sh:
BASE=$(cd $PWD/../../; echo ${PWD##*/})
echo "BASE="$BASE
docker build --build-arg BASE=${BASE} -t company:"${PWD##*/}" .
where the Dockerfile looks like
FROM company:$BASE
Specifically, this yields the build error:
BASE=base_image_name
Sending build context to Docker daemon 5.12kB
Step 1/3 : FROM company:$BASE
invalid reference format
So it seems that docker is not interpretting that build arg correctly.
Dockerfiles don't support shell syntax in general, except for some very limited environment variable expansion.
They do support ARGs that can be passed in from the command line, and an ARG can be used to define the image FROM. So you could start your Dockerfile with
ARG tag
FROM company:${tag:-latest}
and then build the image with
docker build --build-arg tag=$(cd $PWD/../; echo ${PWD##*/}) .
(which is involved enough that you might want to write it into a shell script).
At a very low level, it's also worth remembering that docker build works by making a tar file of the current directory, sending it across an HTTP connection to the Docker daemon, and running the build there. Once that process has happened, any notion of the host directory name is lost. In other words, even if the syntax worked, docker build also doesn't have the capability to know which host directory the Dockerfile is in.
Aha. Found it.
As Jonathon points out, it seems as though you can't easily pull stuff in from your environment into the build system. It seems that you must use Docker build-args.
The solution was to evaluate the variable in the terminal and pass that as a build-arg:
build.sh:
BASE=$(cd $PWD/../; echo ${PWD##*/})
echo "BASE="$BASE
docker build --build-arg BASE=${BASE} -t company:"${PWD##*/}" .
Then inside the Dockerfile of the derived image:
ARG BASE
FROM company:$BASE
You're trying to use bash command substitution in something that isn't consumed by bash.
The [Dockerfile reference[(https://docs.docker.com/engine/reference/builder/) indicates that environment variable substitution is supported by the FROM instruction.
You'll need to instead simply use an environment variable in FROM that you compute outside of the Dockerfile and pass to docker build.

How do I run the build script in this docker container

I am trying to run this container here: https://github.com/mingfang/docker-predictionio. I built the docker image, but I don't know how to run the 'build' script in the repo. I tried ./build but that gives me this error:
invalid argument "." for "-t, --tag" flag: invalid reference format
See 'docker build --help'.
I am not sure why I am getting this error? I tried passing an argument as a name for the docker image like ./build dockerimage as there is an IMAGE variable in the script. But that also throws the same error. Any ideas?
The $IMAGE variable is set by script helper. This script expects that the repo is in a directory named docker-expecter-image-name, so if you used default checkout options your repo would be in directory docker-predictionio and your $IMAGE would be predictionio. My guess is that you checked out the repo under some other directory name, so the variable $IMAGE is not set correctly.
Note: Script run expects the image to be named predictionio, so if the repo directory is named for example docker-mypredictionio then the build script would execute correctly and the run script would not.
This image are not work because use elasticsearch 5.x, the ES 5.x not allow run as root. Try another image.

After building a docker image how can I run the image without pushing to docker hub?

The docs are not very clear to me. I run docker build -f . in the Dockerfile directory, it seems to build successfully, great. I am not sure what to do next, I take a look at the docs https://docs.docker.com/engine/reference/builder/ it tells me When you’re done with your build, you’re ready to look into Pushing a repository to its registry.
Which takes me here https://docs.docker.com/engine/userguide/containers/dockerrepos/#contributing-to-docker-hub I have no interest in publishing it or creating an account.
My other option is to name the build I guess, right? If I run docker build -t <nodebb> . then I get file exists: .. If I run docker build -f <nodebb> . then I get no such file or directory: nodebb.
So I am kind of lost, I wish I could understand the Docs better but I don't and would appreciate the guidance. Thanks!
Your issue with tagging: You cannot use <> in tags
The error that you saw was because '<' and '>' are interpreted by bash. docker build -t <nodebb> . tries to do the following:
It reads the file nodebb and pipes it into docker build -t.
It takes the output of docker build -t < nodebb and writes it to the file .
This fails for several reasons:
-t expects an argument, the tag name
the file . already exists (that's the error you saw)
Generally, you can avoid this by escaping the argument:
docker build -t "<nodebb>" .
However, this will result in another error:
Error parsing reference: "<nodebb>" is not a valid repository/tag
For good reasons, <> are not allowed in tag names. Instead, use a valid tag:
docker build -t nodebb .
Running an image without a tag
You can also run a built image without a tag; if you build an image, the last line will always be something like this:
Successfully built 028edf7c13d1
You can run that image with docker run 028edf7c13d1.

Labelling images in docker

I've got a jenkins server monitoring a git repo and building a docker image on code change. The .git directory is ignored as part of the build, but I want to associate the git commit hash with the image so that I know exactly what version of the code was used to make it and check whether the image is up to date.
The obvious solution is to tag the image with something like "application-name-branch-name:commit-hash", but for many develop branches I only want to keep the last good build, and adding more tags will make cleaning up old builds harder (rather than using the jenkins build number as the image is built, then retagging to :latest and untagging the build number)
The other possibility is labels, but while this looked promising initially, they proved more complicated in practice..
The only way I can see to apply a label directly to an image is in the Dockerfile, which cannot use the build environment variables, so I'd need to use some kind of templating to produce a custom Dockerfile.
The other way to apply a label is to start up a container from the image with some simple command (e.g. bash) and passing in the labels as docker run arguments. The container can then be committed as the new image. This has the unfortunate side effect of making the image's default command whatever was used with the labelling container (so bash in this case) rather than whatever was in the original Dockerfile. For my application I cannot use the actual command, as it will start changing the application state.
None of these seem particularly ideal - has anyone else found a better way of doing this?
Support for this was added in docker v1.9.0, so updating your docker installation to that version would fix your problem if that is OK with you.
Usage is described in the pull-request below:
https://github.com/docker/docker/pull/15182
As an example, take the following Dockerfile file:
FROM busybox
ARG GIT_COMMIT=unknown
LABEL git-commit=$GIT_COMMIT
and build it into an image named test as anyone would do naïvely:
docker build -t test .
Then inspect the test image to check what value ended up for the git-commit label:
docker inspect -f '{{index .ContainerConfig.Labels "git-commit"}}' test
unkown
Now, build the image again, but this time using the --build-arg option:
docker build -t test --build-arg GIT_COMMIT=0123456789abcdef .
Then inspect the test image to check what value ended up for the git-commit label:
docker inspect -f '{{index .ContainerConfig.Labels "git-commit"}}' test
0123456789abcdef
References:
Docker build command documentation for the --build-arg option
Dockerfile reference for the ARG directive
Dockerfile reference for the LABEL directive
You can specify a label on the command line when creating your image. So you would write something like
docker build -t myproject --label "myproject.version=githash" .
instead of hard-coding the version you can also get it directly from git:
docker build -t myproject --label "myproject.version=`git describe`" .
To read out the label from your images you can use docker inspect with a format string:
docker inspect -f '{{index .Config.Labels "myproject.version"}}' myproject
If you are using docker-compose, you could add the following to the build section:
labels:
git-commit-hash: ${COMMIT_HASH}
where COMMIT_HASH is your environment variable, which holds commit hash.

Resources