Is it possible to build image from Dockerfile and run it with a single command?
There is one command docker build
to build a Dockerfile and docker run -it
to run the image.
Is there any combination of these two commands to make it easier to build and run with just one command?
If you want to avoid tagging, docker build -q
outputs nothing but the final image hash, which you can use as the argument to docker run
:
docker run -it $(docker build -q .)
And add --rm
to docker run
if you want the container removed automatically when it exits.
docker run --rm -it $(docker build -q .)
No, there is no single command. But if you tag your image as you build it, it will be easier to run:
docker build -t foo . && docker run -it foo
docker rmi foo
.
I use docker-compose for this convenience since most of the apps I'm building are talking to external services sooner or later, so if I'm going to use it anyway, why not use it from the start. Just have docker-compose.yml as:
version: "3"
services:
app:
build: .
and then just run the app with:
docker-compose up --build app
It will rebuild the image or reuse the container depending on whether there were changes made to the image definition.
Recently I started getting a promo message about using docker scan
after every build.
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Here's what I used to do:
docker build -q .
and here's what is working now:
docker build -q . | head -n1
export DOCKER_SCAN_SUGGEST=false
If you use Makefile, I find this snippet useful:
build:
@docker build . | tee .buildlog
bash: build
@docker run --rm -it $(shell grep "Successfully built" .buildlog | cut -d ' ' -f 3) /bin/bash
You don't need tagging, like in @jonathon-reinhart answer, but you also get the build output.
You can also do docker build
and pipe image name which it outputs to docker run
:
docker build . | tail -n1 | cut -d' ' -f3 | xargs -I{} docker run {}
docker build will give you multi-line text ... Successfully built 18e77bc0d83a
you get the last line with tail -n1
split by ' ' and get 3rd word with cut -d' ' -f3
pass it as argument to run with xargs -I{} docker run {}
| tee /dev/tty
after docker build .
to get the full output!
For anyone looking for a reusable solution, you could install this docker plugin which i created: https://github.com/stasmihailov/docker-script
Then you could build and run a Dockerfile as follows:
docker script ./Dockerfile
Windows PC
Make a run.bat
file. Then in the file add this:
docker build -t foo .
docker run -it foo
To run the file using powershell or cmd do this:
./run.bat
docker-build-and-run
I've created a little helper command for building and running, in a single command. On Linux or Mac, you can add this to your ~/.bash_profile
to make it available in the Terminal.
Usage:
docker-build-and-run BUILD_ARGS [-- RUN_ARGS] [-- RUN_COMMAND]
Examples:
docker-build-and-run . -- npm run test
docker-build-and-run --file ./Dockerfile . -- -v ~/volume:/var/volume -- node server.js
The Script:
Add this to a .sh
file, or add it to your ~/.bash_profile
:
TERM_GREEN="\033[1;32m"
TERM_BLUE="\033[1;34m"
TERM_NC="\033[0m"
docker-build-and-run() {
if [[ -z "$@" ]]; then
echo "
Usage:
docker-build-and-run BUILD_ARGS [-- RUN_ARGS] [-- RUN_COMMAND]
Examples:
docker-build-and-run . -- npm run test
docker-build-and-run --file ./Dockerfile . -- -v ~/volume:/var/volume -- node server.js
"
return
fi
# Extract the segments between the dashes:
BEFORE_THE_DASHES=
while (( "$#" )); do
if [[ "$1" = "--" ]]; then
shift
break
fi
BEFORE_THE_DASHES="$BEFORE_THE_DASHES $1"
shift
done
SEGMENT_1=$BEFORE_THE_DASHES
BEFORE_THE_DASHES=
while (( "$#" )); do
if [[ "$1" = "--" ]]; then
shift
break
fi
BEFORE_THE_DASHES="$BEFORE_THE_DASHES $1"
shift
done
SEGMENT_2=$BEFORE_THE_DASHES
SEGMENT_3=$@
BUILD_ARGS=$SEGMENT_1
RUN_ARGS=$SEGMENT_2
RUN_COMMAND=$SEGMENT_3
if [ -z "$RUN_COMMAND" ]; then
RUN_COMMAND=$RUN_ARGS
RUN_ARGS=
fi
TEMP_TAG=docker-build-and-run-temp
docker rm -f $TEMP_TAG 2>/dev/null
printf "${TERM_GREEN}Building Docker container (${TERM_BLUE}docker build $BUILD_ARGS${TERM_GREEN})${TERM_NC}\n" \
&& docker build --tag $TEMP_TAG $BUILD_ARGS \
&& printf "${TERM_GREEN}Running Docker container (${TERM_BLUE}docker run $RUN_ARGS $RUN_COMMAND${TERM_GREEN})${TERM_NC}\n" \
&& docker run --rm -it $RUN_ARGS --label $TEMP_TAG $TEMP_TAG $RUN_COMMAND
}
Success story sharing
docker build
:/-q
option. To make it quiet, to output only the autogenerated tag. And that's it. Feel free to transform that stdin as you like.docker run ... $(docker build -q .) python foo.py
. The problem is, if the "docker build ..." part accidentally run into error, it turns out the "docker run ..." part would effectively ignore the build error, and proceed and treat the next word (in this case, the "python") as if it were a image name. In other words, it now attempts to runfoo.py
with an image namedpython
. That is not what you would want.