147

What is the difference between docker-compose build and docker build?

Suppose in a dockerized project path there is a docker-compose.yml file:

docker-compose build

And

docker build
Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150

5 Answers5

164

docker-compose can be considered a wrapper around the docker CLI (in fact it is another implementation in python as said in the comments) in order to gain time and avoid 500 characters-long lines (and also start multiple containers at the same time). It uses a file called docker-compose.yml in order to retrieve parameters.

You can find the reference for the docker-compose file format here.

So basically docker-compose build will read your docker-compose.yml, look for all services containing the build: statement and run a docker build for each one.

Each build: can specify a Dockerfile, a context and args to pass to docker.

To conclude with an example docker-compose.yml file :

version: '3.2'

services:
  database:
    image: mariadb
    restart: always
    volumes:
      - ./.data/sql:/var/lib/mysql

  web:
    build:
      dockerfile: Dockerfile-alpine
      context: ./web
    ports:
      - 8099:80
    depends_on:
      - database 

When calling docker-compose build, only the web target will need an image to be built. The docker build command would look like :

docker build -t web_myproject -f Dockerfile-alpine ./web
hugoShaka
  • 4,977
  • 3
  • 17
  • 29
  • 8
    From where did the tag "web_myproject" come from or is it just an example? Can you specify at all image name when building with docker-compose? – eyalzba Jan 30 '19 at 07:18
  • 9
    `web` comes from the container name. `myproject` is the name of the folder you're in. This avoids conflicts if you work on two projects both containing a `web` container. – hugoShaka Jan 30 '19 at 10:53
  • Please take a look at https://stackoverflow.com/questions/33816456/how-to-tag-docker-image-with-docker-compose – hugoShaka Jan 30 '19 at 10:54
  • Based on the `docker-compose.yml` provided above, `web` comes from the service name. – daparic Oct 23 '19 at 18:55
  • 1
    This was my understanding as well, but it seems there are some subtle differences. For example file layer hashes are computed slightly different between the two. – vidstige Feb 06 '20 at 08:03
29

docker-compose build will build the services in the docker-compose.yml file.

https://docs.docker.com/compose/reference/build/

docker build will build the image defined by Dockerfile.

https://docs.docker.com/engine/reference/commandline/build/

Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
Corey Taylor
  • 635
  • 5
  • 12
14

Basically, docker-compose is a better way to use docker than just a docker command.

If the question here is if docker-compose build command, will build a zip kind of thing containing multiple images, which otherwise would have been built separately with usual Dockerfile, then the thinking is wrong.

Docker-compose build, will build individual images, by going into individual service entry in docker-compose.yml.

With docker images, command, we can see all the individual images being saved as well.

The real magic is docker-compose up.

This one will basically create a network of interconnected containers, that can talk to each other with name of container similar to a hostname.

GingerBeer
  • 888
  • 10
  • 11
7

Adding to the first answer...

You can give the image name and container name under the service definition.

e.g. for the service called 'web' in the below docker-compose example, you can give the image name and container name explicitly, so that docker does not have to use the defaults.

Otherwise the image name that docker will use will be the concatenation of the folder (Directory) and the service name. e.g. myprojectdir_web

So it is better to explicitly put the desired image name that will be generated when docker build command is executed.

e.g. image: mywebserviceImage container_name: my-webServiceImage-Container

example docker-compose.yml file :

version: '3.2'
services:
  web:
    build:
      dockerfile: Dockerfile-alpine
      context: ./web
    ports:
      - 8099:80
    image: mywebserviceImage
    container_name: my-webServiceImage-Container
    depends_on:
      - database
shivbits
  • 101
  • 1
  • 5
  • Specifying the subdir as value of `build:` forces you to have the exact filename as `Dockerfile`. For example, in `build: ./web`.So the use of `context:` is a good one! – daparic Oct 23 '19 at 19:16
6

Few additional words about the difference between docker build and docker-compose build. Both have an option for building images using an existing image as a cache of layers.

Unfortunately, up until now, at this level, images made by one are not compatible with the other as a cache of layers (Ids are not compatible). However, docker-compose v1.25.0 (2019-11-18), introduces an experimental feature COMPOSE_DOCKER_CLI_BUILD so that docker-compose uses native docker builder (therefore, images made by docker build can be used as a cache of layers for docker-compose build)

Pascal H.
  • 1,431
  • 8
  • 18