332

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?

Viacheslav Shalamov
  • 4,149
  • 6
  • 44
  • 66
Twinkle
  • 3,431
  • 2
  • 9
  • 5

10 Answers10

549

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 .)
abernier
  • 27,030
  • 20
  • 83
  • 114
starthal
  • 5,629
  • 1
  • 15
  • 6
  • 17
    Better than the accepted answer, since it doesn't clutter the local image repository – InsOp Oct 18 '18 at 12:10
  • 41
    @InsOp Actually, this produces local images, too. They're just not tagged. – Jonathon Reinhart Nov 23 '18 at 00:58
  • 7
    Sadly this doesn't show you the regular build output from `docker build` :/ – Lion Sep 28 '19 at 16:03
  • 5
    @Lion that the point of `-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. – Salathiel Genese Jan 26 '20 at 08:25
  • 2
    To get the output of the build, you should adapt the [answer of Viacheslav Shalamov](https://stackoverflow.com/a/59220656/3207406) : `docker build . | tee /dev/tty | tail -n1 | cut -d' ' -f3 | xargs -I{} docker run --rm {}` – oliverpool Apr 05 '20 at 15:33
  • 3
    This answer is a nice technique! I use it for a while, but then realize it is undesirable whenever I'd need to append a run-time command at the end, such as `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 run `foo.py` with an image named `python`. That is not what you would want. – RayLuo Jan 17 '21 at 01:37
  • 2
    For people that have problems with specifying a Dockerfile that is in another folder, here you have an example of how you can do it: docker run --rm -it $(docker build -q -f testFolder/Dockerfile .) – Pedro Rodrigues Dec 16 '21 at 13:21
  • Doesn't work for me: `Error: /usr/app/node_modules/bcrypt/lib/binding/napi-v3/bcrypt_lib.node: invalid ELF header` – geoidesic Jul 28 '22 at 16:07
  • @RayLuo: Fix: `docker run ... $(docker build -q . || echo build_broken) python foo.py`. Obviously won't fix the underlying error, but it avoids using `python` as an image name. – MSalters Aug 09 '22 at 12:10
  • I dont need that `-it` to run ^^ – Nam G VU Oct 14 '22 at 10:52
310

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
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
75

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.

Pang
  • 9,564
  • 146
  • 81
  • 122
Dejan Simic
  • 7,820
  • 2
  • 28
  • 15
7

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.

tavlima
  • 189
  • 2
  • 11
7

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 --quiet .

and here's what is working now:

docker build --quiet . | head -n1
Sridhar Sarnobat
  • 25,183
  • 12
  • 93
  • 106
bozdoz
  • 12,550
  • 7
  • 67
  • 96
  • 5
    See https://github.com/docker/scan-cli-plugin/issues/149#issuecomment-823969364 on how to disable that message permanently. `export DOCKER_SCAN_SUGGEST=false` – Tobias Aug 06 '21 at 19:32
  • 2
    @bozdoz What does a promo message have to do with building and running in one command? – AlxVallejo Jun 16 '22 at 14:28
  • @AlxVallejo See above comment. Docker is printing a line about using Snyk after each build. So, as per my answer, what I used to do wasn't working anymore (because docker build was no longer printing solely the image hash) – bozdoz Jul 13 '22 at 15:30
  • 1
    I'm not sure why this is posted as a separate answer. I was confused just like AlxVallejo especially since this response appears first in the thread. – Sridhar Sarnobat Sep 21 '22 at 02:41
6

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 {}
Viacheslav Shalamov
  • 4,149
  • 6
  • 44
  • 66
  • 3
    add [`| tee /dev/tty`](https://stackoverflow.com/a/5677265/3207406) after `docker build .` to get the full output! – oliverpool Apr 05 '20 at 15:31
3

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
2

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
}

Scott Rippey
  • 15,614
  • 5
  • 70
  • 85
1

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
Rob
  • 6,758
  • 4
  • 46
  • 51
0

Consider automatically giving a name to the generated image:

alias docker-up=docker build -t $(basename $PWD) . && docker run -it $(basename $PWD)