Compose: Don't always start a service defined in yml when docker-compose up

Created on 15 Jun 2015  路  11Comments  路  Source: docker/compose

When you issue a docker-compose up, all services always start. While you're iterating over some code, this isn't always great (some background: we use consul for service discovery once our images are started, so we don't rely on links too heavily. Having said that, our consul service images do link to one another).

When I'm heavily iterating on the code in a particular container and it requires many restarts, it's much easier to have all other containers controlled by docker-compose, and the container you're iterating on to be controlled separately.

The yaml could be something like:

conductor:
    build: ./conductor
    volumes:
        - /data/consul/conductor:/data/consul:rw
consulagent:
    build: ./consul
    links:
        - conductor:consul-agent
db:
    build: ./db
    links:
        - conductor:consul-agent
cache:
    build: ./cache
    links:
        - conductor:consul-agent
static:
    build: ./static
    links:
        - conductor:consul-agent
    ports:
        - 80:80
        - 443:443
    environment:
        - DEBUG=debug,info,error
        - NODE_ENV=development
consului:
    build: ./consul-ui
    links:
        - conductor:consul-agent
    ports:
        - 8500:8500
app:
    build: ./app
    links:
        - conductor:consul-agent
    environment:
        - NODE_ENV=development
        - APP_PORT=4000
    always-start: false

Notice the always-start property, being set to false. This would allow me to have a workflow of:

$ docker-compose up -d
$ docker-compose up app

I could then docker compose stop app and docker compose up app independently of all other services. To achieve this at present, you have comment/uncomment the app service within the yaml file.

Most helpful comment

That could work for sure. However, to build the entire suite of services, you'd need to issue two commands:

$ docker-compose build
$ docker-compose -f app.yml build

It would be preferable to have this in one command...

All 11 comments

You could do this:

$ docker-compose up -d
$ docker-compose -f app.yml up

[edit]
... and use external_links.

That could work for sure. However, to build the entire suite of services, you'd need to issue two commands:

$ docker-compose build
$ docker-compose -f app.yml build

It would be preferable to have this in one command...

+1

This is a duplicate of many previous issues (#1439, #697, #942, #1041, #1451, etc)

If a container isn't going to start and run with the rest of the containers, it's not really "part of the composition", so I'm -1 on any new keys to define different behaviours for services.

There are however, already a few ways to handle this scenario:

  • you can include the service in the config with a no-op cmd, and then later run it with docker-compose run
  • you could exclude it from the core config, and instead include it in a config that uses extends to pull in services from the core config

For your specific case, there is a new experimental flag in the docker-compose 1.3 release candidate. docker-compose up --x-smart-recreate which will only recreate and restart the containers that have changed, and leave the rest running.

+1, ideally allow the flag to be set from an environment variable. We have a few build/run variants, to this feature would be great

For my team I made a script that basically does this :

docker rm -vf project_app_1
docker build -t project_app app
docker-compose up -d --no-recreate --no-build

This works well.
Since 1.3.0rc1 --x-smart-recreate may resolve our problem.

Thanks for the suggestion! I've created an issue here to aggregate many similar suggestions: https://github.com/docker/compose/issues/1896

This feature would be tremendously useful. For example, I have an program that runs an interactive terminal, and passes configuration parameters to the running services (e.g. debug verbosity). Because it uses the same network, volumes, etc., as the other services, it makes sense to keep it in the same compilation. Running it from it's own compilation is doable, but it requires hard-coding the names of the volumes into the compose file.

The no-op command idea is fine, but not very elegant, especially if there's a long path to the executable. Another option would be to run a script inside the container that somehow tests what kind of environment it's in, and determine if it was run via up. But, again, providing a config parameter for this would be much cleaner.

This helps for me:

docker-compose up --scale <service>=0

Apparently docker-compose up --scale <service>=0 will still build <service>.

If you don't like typing the extra arguments in the CLI you could always do something like

services:
 <service>:
  entrypoint: "bash -c"
  command: "exit 0"

I implemented this using environment variables. Solution on stackoverflow: https://stackoverflow.com/a/61107015/10534470

Was this page helpful?
0 / 5 - 0 ratings