Docker Compose Up vs Start and Down vs Stop [Difference]

If you’re new to Docker Compose and learn it by following several tutorials, you might come across terms like

docker-compose up, docker-compose up -d, docker-compose stop, docker-compose down, or even docker-compose stop.

These terms are enough to confuse a docker beginner because many of these docker-compose commands seem to behave in a very similar way.

In fact, it can be especially difficult at first to immediately tell the difference between docker-compose up and docker-compose start.

Isn’t starting a container through Docker Compose the same as running the up command? Not exactly.

Let me explain everything to you in detail.

Differences between Docker Compose up, up -d, stop, start, down, and

down -v

What these commands do:

The Docker Compose up command deploys web application services and creates new containers from the Docker image along with the network settings, volumes, and all configurations specified in the Docker Compose file. When you specify -d, it means that it tells you to run it in separate mode so that it runs in the background giving you control of the terminal (discussed in a moment through some examples below).

The Docker Compose

stop command stops all services associated with a Docker Compose configuration. It does NOT delete any associated container or volume or internal network.

The Docker Compose

startup command will start the stopped services as specified in a stopped configuration based on the same Docker Compose file.

The Docker Compose

down command stops all services associated with a Docker Compose configuration. Unlike stop, it also removes any containers and internal networks associated with services. But NOT internally specified volumes. To do that too, you need to additionally specify the -v flag after the down command.

This sounds similar to Docker’s run vs start command, right?

Enough theory, let’s look at some practical examples now.

Understand the difference with the practical example

If you want to follow the examples, make sure you already have the Docker installer and Docker

Compose.

Let’s say you’re using a Docker Compose-based Ghost blog setup running on your Linux server

.

In all our auto-host tutorials, I mainly tend to use the -d brand whenever we deploy our configurations on our servers. But what if you don’t specify?

[email protected]:~/ghost$ docker-compose up Pulling ghost (ghost:4.20.3)… 4.20.3: Library/Ghost Extraction b380bbd43752: Full Extract 8d36a6ce056a: Full Extract f75fe68b8e22: Full Extract 44f6d143e12f: Full Extract 0ebe8063dedd: Full Extract f984e0e37c5a: Complete Extraction ce2320facea8: Complete Extraction 898c3dbc1716: Full Extraction 45c37559f24a: Full Extraction Summary: sha256:b332684117bfa05329298712ad0ffcfc4a83ce6314332e073978f46be3c05e81 Status: Downloaded Latest image for ghost:4.20.3 Creating ghost_ghost_1 … Done Attach to ghost_ghost_1 ghost_1 | [2021-10-26 07:02:05] INFO Ghost is running in production… ghost_1 | [2021-10-26 07:02:05] INFO Your site is now available on https://ghost.domain.com/ ghost_1 | [2021-10-26 07:02:05] INFO Ctrl+C to close ghost_1 | [2021-10-26 07:02:05] INFO Ghost server started at 0.369s ghost_1 | [2021-10-26 07:02:06] WARN The state of the database requires initialization. ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Entries | [2021-10-26 07:02:06] INFO Table creation: posts_meta ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Users | [2021-10-26 07:02:06] INFO Table creation: oauth ghost_1 | [2021-10-26 07:02:06] INFO Table creation: posts_authors ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Roles | [2021-10-26 07:02:06] INFO Table creation: roles_users ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Permissions | [2021-10-26 07:02:06] INFO Table creation: permissions_users ghost_1 | [2021-10-26 07:02:06] INFO Table creation: permissions_roles ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Configuration | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Tags | [2021-10-26 07:02:06] INFO Table creation: posts_tags ghost_1 | [2021-10-26 07:02:06] INFO Table creation: invites ghost_1 | [2021-10-26 07:02:06] INFO Table creation: brute ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Sessions | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Integrations | [2021-10-26 07:02:06] INFO Table creation: webhooks ghost_1 | [2021-10-26 07:02:06] INFO Table creation: api_keys ghost_1 | [2021-10-26 07:02:06] INFO Table creation: mobiledoc_revisions ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: Members ghost_1 | [2021-10-26 07:02:06] INFO Table creation: ghost_1 products | [2021-10-26 07:02:06] INFO Table creation: ghost_1 offers | [2021-10-26 07:02:06] INFO Table creation: benefits ghost_1 | [2021-10-26 07:02:06] INFO Table creation: products_benefits ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_products ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_payment_events ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_login_events ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_email_change_events ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_status_events ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_product_events ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_paid_subscription_events ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Tags | [2021-10-26 07:02:06] INFO Table creation: members_labels ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_stripe_customers ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_stripe_customers_subscriptions ghost_1 | [2021-10-26 07:02:06] INFO Table creation: offer_redemptions ghost_1 | [2021-10-26 07:02:06] INFO Table creation: members_subscribe_events ghost_1 | [2021-10-26 07:02:06] INFO Table creation: stripe_products ghost_1 | [2021-10-26 07:02:06] INFO Table creation: stripe_prices ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Actions | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Emails | [2021-10-26 07:02:06] INFO Table creation: email_batches ghost_1 | [2021-10-26 07:02:06] INFO Table creation: email_recipients ghost_1 | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Tokens | [2021-10-26 07:02:06] INFO Table Creation: ghost_1 Fragments | [2021-10-26 07:02:06] INFO Table creation: temp_member_analytic_events ghost_1 | [2021-10-26 07:02:06] INFO Table creation: custom_theme_settings ghost_1 | [2021-10-26 07:02:06] Model INFO: Product ghost_1 | [2021-10-26 07:02:06] Model INFO: Tag ghost_1 | [2021-10-26 07:02:06] INFO Model: Role ghost_1 | [2021-10-26 07:02:06] Model INFO: ghost_1 Permit | [2021-10-26 07:02:07] INFO Model: User ghost_1 | [2021-10-26 07:02:07] Model INFO: Post ghost_1 | [2021-10-26 07:02:08] INFO Model: ghost_1 Integration | [2021-10-26 07:02:08] INFO Relationship: Role to ghost_1 Permissions | [2021-10-26 07:02:08] INFO Relationship: Publish to ghost_1 of Tags | [2021-10-26 07:02:08] INFO Relationship: User-to-Role ghost_1 | [2021-10-26 07:02:08] The INFO database is ready. ghost_1 | [2021-10-26 07:02:08] INFO Ghost Database List in 3.309s ghost_1 | [2021-10-26 07:02:09] INFO Ghost booted in 4.457s ghost_1 | [2021-10-26 07:02:09] INFO Add downloaded work to queue ghost_1 | [2021-10-26 07:02:09] INFO Schedule update work-check on 49 27 22 * * *. Next run on: Tue Oct 26 2021 22:27:49 GMT+0000 (Coordinated Universal Time) ghost_1 | [2021-10-26 07:02:51] INFO “GET /favicon.ico” 200 7ms ghost_1 | [2021-10-26 07:02:51] INFO “GET /” 200 605ms ghost_1 | [2021-10-26 07:02:51] INFO “GET /assets/built/screen.css?v=dde6c321bb” 200 5ms ghost_1 | [2021-10-26 07:02:51] INFO “GET /assets/built/casper.js?v=dde6c321bb” 200 3ms ghost_1 | [2021-10-26 07:02:52] INFO “GET /members/api/member/” 204 1ms ghost_1 | [2021-10-26 07:02:52] INFO “GET /members/api/site/” 200 14ms ghost_1 | [2021-10-26 07:02:52] INFO “GET /favicon.ico” 200 2ms

So you see it? Without the -d option, it starts its settings, but it happens in a verbose mode without returning to the terminal request. A bit useful, isn’t it? When you open the browser and access the ghost blog, you will find it accessible in a few moments. But what happens if you leave the console with Ctrl + Z? It will keep the process running in the background, and you can check that using the

docker ps command:[email protected]:~/ghost$ docker ps CREATED CONTAINER ID IMAGE COMMAND STATE PORT NAMES 563a45d049cf ghost:4.20.3 “docker-entrypoint.s…” 3 minutes ago Up to 3 minutes 2368/tcp ghost_ghost_1

But what about the container if you used Ctrl+C instead? The process is killed immediately.

[email protected]: ~/ghost$ docker ps CREATED CONTAINER ID IMAGE COMMAND STATE PORT NAMES

When you use the -d option, what it does is very similar to Ctrl + Z: it separates from the console and continues to run the container in the background and also prints the new container name (ghost_ghost_1 in this case).

Now, instead of using docker-compose down, let’s use docker-compose stop:[email protected]:~/ghost$

docker-compose stop

[email protected]:~/ghost$

Now let’s review our running containers. As expected, there should be none

:[email protected]:~/ghost$ docker-compose ps Name Command State Ports – ghost_ghost_1 docker-entrypoint.sh node… Output 0

Note that I did not use docker ps. Instead, I ran docker-compose ps because I wanted to show you another way to check output status 0. This means that the container has exited/stopped.

Let’s check this again with docker ps -a. The -a flag will also search for stopped containers

:[email protected]:~/ghost$ docker ps -a CREATED CONTAINER ID IMAGE COMMAND STATE PORT NAMES 44d09e778a91 ghost:4.20.3 “docker-entrypoint.s…” 8 minutes ago Sold (0) 7 minutes ago ghost_ghost_1

What is docker-compose start then?

Docker Compose Start only makes sense when you haven’t deleted any containers with docker-compose below (I haven’t done that yet in this tutorial command line). So basically, the difference here is that it starts containers that have been stopped and not deleted.

So first, let’s use start instead of up now and see what happens

:[email protected]:~/ghost$ docker-compose start Starting ghost… done [email protected]:~/ghost$

What happens now is that the stopped container starts again

:[email protected]:~/ghost$ docker-compose ps Name Command State Ports – ghost_ghost_1 docker-entrypoint.sh node … Up to 2368/tcp

There you have it. The state is now behind exit 0. You can also check again with the docker version of the command

:[email protected]:~/ghost$ docker ps CREATED CONTAINER ID IMAGE COMMAND STATE PORT NAMES 44d09e778a91 ghost:4.20.3 “docker-entrypoint.s…” 22 minutes ago Up About one minute ago 2368/tcp ghost_ghost_1

Now let’s run the stop command again.

[email protected]:~/ghost$ docker-compose stop Stop ghost_ghost_1 …

Now you are aware of what the status of the container is. You can use the up or start command to make it work again. Note that you can also run the down in this state without starting the services again

:[email protected]:~/ghost$ docker-compose down Removing ghost_ghost_1 … done The network network is external, ignoring

The container has now been deleted. If there were internal networks specified within the Docker Compose file, they would also have been deleted. Because the network is external, it is omitted from deletion. If you had specified the -v flag additionally, it would have been removed as well!

[email protected]:~/ghost$ docker-compose down -v Stop ghost_ghost_1 … made Removing ghost_ghost_1 … done The network network is external, skipping the volume ghost is external, skipping

Always be double cautious with your data!

Also, you cannot use start at this stage. Works only for stopped configurations

:[email protected]:~/ghost$ docker-compose start Starting ghost… error ERROR: No containers to start In such case, you should use docker-compose up or docker-compose up -d once again. [email protected]:~/ghost$

docker-compose up -d

Creating ghost_ghost_1 … done [email protected]:~/ghost$

Summary

I hope this article has given you a better understanding of up vs up -d vs start, as well as stop vs down and down -v for Docker Compose

.

This comprehensive explanatory guide should make your day-to-day management of dockers much easier and much less overwhelming from now on. Depending on scenario to scenario, especially in production systems, the particular command you choose to resolve a situation will, of course, differ in how you implement it.

If you have any ideas, queries, or suggestions to share, please leave a comment below.

Contact US