Merge pull request #3060 from aanand/doc-updates

Doc updates
This commit is contained in:
Daniel Nephin 2016-03-02 20:12:24 -08:00
commit 9da9555f10
15 changed files with 340 additions and 171 deletions

View file

@ -10,6 +10,7 @@ RUN svn checkout https://github.com/docker/kitematic/trunk/docs /docs/content/ki
RUN svn checkout https://github.com/docker/toolbox/trunk/docs /docs/content/toolbox
RUN svn checkout https://github.com/docker/opensource/trunk/docs /docs/content/project
ENV PROJECT=compose
# To get the git info for this repo
COPY . /src

View file

@ -59,6 +59,14 @@ optionally [dockerfile](#dockerfile) and [args](#args).
args:
buildno: 1
If you specify `image` as well as `build`, then Compose tags the built image
with the tag specified in `image`:
build: ./dir
image: webapp
This will result in an image tagged `webapp`, built from `./dir`.
> **Note**: In the [version 1 file format](#version-1), `build` is different in
> two ways:
>
@ -95,13 +103,13 @@ specified.
> **Note**: In the [version 1 file format](#version-1), `dockerfile` is
> different in two ways:
>
> - It appears alongside `build`, not as a sub-option:
>
> build: .
> dockerfile: Dockerfile-alternate
> - Using `dockerfile` together with `image` is not allowed. Attempting to do
> so results in an error.
* It appears alongside `build`, not as a sub-option:
build: .
dockerfile: Dockerfile-alternate
* Using `dockerfile` together with `image` is not allowed. Attempting to do so results in an error.
#### args
@ -195,6 +203,11 @@ Simple example:
db:
image: postgres
> **Note:** `depends_on` will not wait for `db` and `redis` to be "ready" before
> starting `web` - only until they have been started. If you need to wait
> for a service to be ready, see [Controlling startup order](startup-order.md)
> for more on this problem and strategies for solving it.
### dns
Custom DNS servers. Can be a single value or a list.
@ -340,13 +353,22 @@ An entry with the ip address and hostname will be created in `/etc/hosts` inside
### image
Tag or partial image ID. Can be local or remote - Compose will attempt to
pull if it doesn't exist locally.
Specify the image to start the container from. Can either be a repository/tag or
a partial image ID.
image: ubuntu
image: orchardup/postgresql
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd
If the image does not exist, Compose attempts to pull it, unless you have also
specified [build](#build), in which case it builds it using the specified
options and tags it with the specified tag.
> **Note**: In the [version 1 file format](#version-1), using `build` together
> with `image` is not allowed. Attempting to do so results in an error.
### labels
Add metadata to containers using [Docker labels](https://docs.docker.com/engine/userguide/labels-custom-metadata/). You can use either an array or a dictionary.

View file

@ -10,10 +10,9 @@ weight=4
<![end-metadata]-->
# Quickstart: Compose and Django
# Quickstart: Docker Compose and Django
This quick-start guide demonstrates how to use Compose to set up and run a
simple Django/PostgreSQL app. Before starting, you'll need to have
This quick-start guide demonstrates how to use Docker Compose to set up and run a simple Django/PostgreSQL app. Before starting, you'll need to have
[Compose installed](install.md).
## Define the project components
@ -119,12 +118,23 @@ In this step, you create a Django started project by building the image from the
-rwxr-xr-x 1 root root manage.py
-rw-rw-r-- 1 user user requirements.txt
The files `django-admin` created are owned by root. This happens because
the container runs as the `root` user.
If you are running Docker on Linux, the files `django-admin` created are owned
by root. This happens because the container runs as the root user. Change the
ownership of the the new files.
4. Change the ownership of the new files.
sudo chown -R $USER:$USER .
sudo chown -R $USER:$USER .
If you are running Docker on Mac or Windows, you should already have ownership
of all files, including those generated by `django-admin`. List the files just
verify this.
$ ls -l
total 32
-rw-r--r-- 1 user staff 145 Feb 13 23:00 Dockerfile
drwxr-xr-x 6 user staff 204 Feb 13 23:07 composeexample
-rw-r--r-- 1 user staff 159 Feb 13 23:02 docker-compose.yml
-rwxr-xr-x 1 user staff 257 Feb 13 23:07 manage.py
-rw-r--r-- 1 user staff 16 Feb 13 23:01 requirements.txt
## Connect the database
@ -171,6 +181,8 @@ In this section, you set up the database connection for Django.
Docker host. If you are using a Docker Machine VM, you can use the
`docker-machine ip MACHINE_NAME` to get the IP address.
![Django example](images/django-it-worked.png)
## More Compose documentation
- [User guide](index.md)

View file

@ -290,31 +290,17 @@ replaces the old value.
# result
command: python otherapp.py
In the case of `build` and `image`, using one in the local service causes
Compose to discard the other, if it was defined in the original service.
Example of image replacing build:
# original service
build: .
# local service
image: redis
# result
image: redis
Example of build replacing image:
# original service
image: redis
# local service
build: .
# result
build: .
> **Note:** In the case of `build` and `image`, when using
> [version 1 of the Compose file format](compose-file.md#version-1), using one
> option in the local service causes Compose to discard the other option if it
> was defined in the original service.
>
> For example, if the original service defines `image: webapp` and the
> local service defines `build: .` then the resulting service will have
> `build: .` and no `image` option.
>
> This is because `build` and `image` cannot be used together in a version 1
> file.
For the **multi-value options** `ports`, `expose`, `external_links`, `dns` and
`dns_search`, Compose concatenates both sets of values:

View file

@ -15,7 +15,13 @@ weight=90
If you dont see your question here, feel free to drop by `#docker-compose` on
freenode IRC and ask the community.
## Why do my services take 10 seconds to stop?
## Can I control service startup order?
Yes - see [Controlling startup order](startup-order.md).
## Why do my services take 10 seconds to recreate or stop?
Compose stop attempts to stop a container by sending a `SIGTERM`. It then waits
for a [default timeout of 10 seconds](./reference/stop.md). After the timeout,
@ -40,6 +46,12 @@ in your Dockerfile.
* If you are able, modify the application that you're running to
add an explicit signal handler for `SIGTERM`.
* Set the `stop_signal` to a signal which the application knows how to handle:
web:
build: .
stop_signal: SIGINT
* If you can't modify the application, wrap the application in a lightweight init
system (like [s6](http://skarnet.org/software/s6/)) or a signal proxy (like
[dumb-init](https://github.com/Yelp/dumb-init) or
@ -84,30 +96,6 @@ specify the filename to use, for example:
docker-compose -f docker-compose.json up
```
## How do I get Compose to wait for my database to be ready before starting my application?
Unfortunately, Compose won't do that for you but for a good reason.
The problem of waiting for a database to be ready is really just a subset of a
much larger problem of distributed systems. In production, your database could
become unavailable or move hosts at any time. The application needs to be
resilient to these types of failures.
To handle this, the application would attempt to re-establish a connection to
the database after a failure. If the application retries the connection,
it should eventually be able to connect to the database.
To wait for the application to be in a good state, you can implement a
healthcheck. A healthcheck makes a request to the application and checks
the response for a success status code. If it is not successful it waits
for a short period of time, and tries again. After some timeout value, the check
stops trying and report a failure.
If you need to run tests against your application, you can start by running a
healthcheck. Once the healthcheck gets a successful response, you can start
running your tests.
## Should I include my code with `COPY`/`ADD` or a volume?
You can add your code to the image using `COPY` or `ADD` directive in a

View file

@ -12,7 +12,7 @@ weight=-85
# Getting Started
On this page you build a simple Python web application running on Compose. The
On this page you build a simple Python web application running on Docker Compose. The
application uses the Flask framework and increments a value in Redis. While the
sample uses Python, the concepts demonstrated here should be understandable even
if you're not familiar with it.

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View file

@ -24,11 +24,14 @@ CI workflows. You can learn more about each case in
Using Compose is basically a three-step process.
1. Define your app's environment with a `Dockerfile` so it can be
reproduced anywhere.
2. Define the services that make up your app in `docker-compose.yml` so
they can be run together in an isolated environment.
3. Lastly, run `docker-compose up` and Compose will start and run your entire app.
1. Define your app's environment with a `Dockerfile` so it can be reproduced
anywhere.
2. Define the services that make up your app in `docker-compose.yml`
so they can be run together in an isolated environment.
3. Lastly, run
`docker-compose up` and Compose will start and run your entire app.
A `docker-compose.yml` looks like this:
@ -37,16 +40,16 @@ A `docker-compose.yml` looks like this:
web:
build: .
ports:
- "5000:5000"
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
- redis
redis:
image: redis
volumes:
logvolume01: {}
For more information about the Compose file, see the
[Compose file reference](compose-file.md)
@ -80,14 +83,12 @@ The features of Compose that make it effective are:
### Multiple isolated environments on a single host
Compose uses a project name to isolate environments from each other. You can use
this project name to:
Compose uses a project name to isolate environments from each other. You can make use of this project name in several different contexts:
* on a dev host, to create multiple copies of a single environment (ex: you want
to run a stable copy for each feature branch of a project)
* on a dev host, to create multiple copies of a single environment (e.g., you want to run a stable copy for each feature branch of a project)
* on a CI server, to keep builds from interfering with each other, you can set
the project name to a unique build number
* on a shared host or dev host, to prevent different projects which may use the
* on a shared host or dev host, to prevent different projects, which may use the
same service names, from interfering with each other
The default project name is the basename of the project directory. You can set
@ -148,9 +149,7 @@ started guide" to a single machine readable Compose file and a few commands.
An important part of any Continuous Deployment or Continuous Integration process
is the automated test suite. Automated end-to-end testing requires an
environment in which to run tests. Compose provides a convenient way to create
and destroy isolated testing environments for your test suite. By defining the full
environment in a [Compose file](compose-file.md) you can create and destroy these
environments in just a few commands:
and destroy isolated testing environments for your test suite. By defining the full environment in a [Compose file](compose-file.md) you can create and destroy these environments in just a few commands:
$ docker-compose up -d
$ ./run_tests
@ -159,9 +158,7 @@ environments in just a few commands:
### Single host deployments
Compose has traditionally been focused on development and testing workflows,
but with each release we're making progress on more production-oriented features.
You can use Compose to deploy to a remote Docker Engine. The Docker Engine may
be a single instance provisioned with
but with each release we're making progress on more production-oriented features. You can use Compose to deploy to a remote Docker Engine. The Docker Engine may be a single instance provisioned with
[Docker Machine](https://docs.docker.com/machine/) or an entire
[Docker Swarm](https://docs.docker.com/swarm/) cluster.

View file

@ -9,9 +9,9 @@ weight=5
+++
<![end-metadata]-->
## Quickstart: Compose and Rails
## Quickstart: Docker Compose and Rails
This Quickstart guide will show you how to use Compose to set up and run a Rails/PostgreSQL app. Before starting, you'll need to have [Compose installed](install.md).
This Quickstart guide will show you how to use Docker Compose to set up and run a Rails/PostgreSQL app. Before starting, you'll need to have [Compose installed](install.md).
### Define the project
@ -30,7 +30,9 @@ Dockerfile consists of:
RUN bundle install
ADD . /myapp
That'll put your application code inside an image that will build a container with Ruby, Bundler and all your dependencies inside it. For more information on how to write Dockerfiles, see the [Docker user guide](https://docs.docker.com/engine/userguide/dockerimages/#building-an-image-from-a-dockerfile) and the [Dockerfile reference](https://docs.docker.com/engine/reference/builder/).
That'll put your application code inside an image that will build a container
with Ruby, Bundler and all your dependencies inside it. For more information on
how to write Dockerfiles, see the [Docker user guide](https://docs.docker.com/engine/userguide/dockerimages/#building-an-image-from-a-dockerfile) and the [Dockerfile reference](https://docs.docker.com/engine/reference/builder/).
Next, create a bootstrap `Gemfile` which just loads Rails. It'll be overwritten in a moment by `rails new`.
@ -41,7 +43,11 @@ You'll need an empty `Gemfile.lock` in order to build our `Dockerfile`.
$ touch Gemfile.lock
Finally, `docker-compose.yml` is where the magic happens. This file describes the services that comprise your app (a database and a web app), how to get each one's Docker image (the database just runs on a pre-made PostgreSQL image, and the web app is built from the current directory), and the configuration needed to link them together and expose the web app's port.
Finally, `docker-compose.yml` is where the magic happens. This file describes
the services that comprise your app (a database and a web app), how to get each
one's Docker image (the database just runs on a pre-made PostgreSQL image, and
the web app is built from the current directory), and the configuration needed
to link them together and expose the web app's port.
version: '2'
services:
@ -64,22 +70,38 @@ using `docker-compose run`:
$ docker-compose run web rails new . --force --database=postgresql --skip-bundle
First, Compose will build the image for the `web` service using the
`Dockerfile`. Then it'll run `rails new` inside a new container, using that
image. Once it's done, you should have generated a fresh app:
First, Compose will build the image for the `web` service using the `Dockerfile`. Then it'll run `rails new` inside a new container, using that image. Once it's done, you should have generated a fresh app:
$ ls
Dockerfile app docker-compose.yml tmp
Gemfile bin lib vendor
Gemfile.lock config log
README.rdoc config.ru public
Rakefile db test
$ ls -l
total 56
-rw-r--r-- 1 user staff 215 Feb 13 23:33 Dockerfile
-rw-r--r-- 1 user staff 1480 Feb 13 23:43 Gemfile
-rw-r--r-- 1 user staff 2535 Feb 13 23:43 Gemfile.lock
-rw-r--r-- 1 root root 478 Feb 13 23:43 README.rdoc
-rw-r--r-- 1 root root 249 Feb 13 23:43 Rakefile
drwxr-xr-x 8 root root 272 Feb 13 23:43 app
drwxr-xr-x 6 root root 204 Feb 13 23:43 bin
drwxr-xr-x 11 root root 374 Feb 13 23:43 config
-rw-r--r-- 1 root root 153 Feb 13 23:43 config.ru
drwxr-xr-x 3 root root 102 Feb 13 23:43 db
-rw-r--r-- 1 user staff 161 Feb 13 23:35 docker-compose.yml
drwxr-xr-x 4 root root 136 Feb 13 23:43 lib
drwxr-xr-x 3 root root 102 Feb 13 23:43 log
drwxr-xr-x 7 root root 238 Feb 13 23:43 public
drwxr-xr-x 9 root root 306 Feb 13 23:43 test
drwxr-xr-x 3 root root 102 Feb 13 23:43 tmp
drwxr-xr-x 3 root root 102 Feb 13 23:43 vendor
The files `rails new` created are owned by root. This happens because the
container runs as the `root` user. Change the ownership of the new files.
If you are running Docker on Linux, the files `rails new` created are owned by
root. This happens because the container runs as the root user. Change the
ownership of the the new files.
sudo chown -R $USER:$USER .
sudo chown -R $USER:$USER .
If you are running Docker on Mac or Windows, you should already have ownership
of all files, including those generated by `rails new`. List the files just to
verify this.
Uncomment the line in your new `Gemfile` which loads `therubyracer`, so you've
got a Javascript runtime:
@ -132,6 +154,14 @@ Finally, you need to create the database. In another terminal, run:
That's it. Your app should now be running on port 3000 on your Docker daemon. If you're using [Docker Machine](https://docs.docker.com/machine/), then `docker-machine ip MACHINE_VM` returns the Docker host IP address.
![Rails example](images/rails-welcome.png)
>**Note**: If you stop the example application and attempt to restart it, you might get the
following error: `web_1 | A server is already running. Check
/myapp/tmp/pids/server.pid.` One way to resolve this is to delete the file
`tmp/pids/server.pid`, and then re-start the application with `docker-compose
up`.
## More Compose documentation

88
docs/startup-order.md Normal file
View file

@ -0,0 +1,88 @@
<!--[metadata]>
+++
title = "Controlling startup order"
description = "How to control service startup order in Docker Compose"
keywords = "documentation, docs, docker, compose, startup, order"
[menu.main]
parent="workw_compose"
weight=90
+++
<![end-metadata]-->
# Controlling startup order in Compose
You can control the order of service startup with the
[depends_on](compose-file.md#depends-on) option. Compose always starts
containers in dependency order, where dependencies are determined by
`depends_on`, `links`, `volumes_from` and `network_mode: "service:..."`.
However, Compose will not wait until a container is "ready" (whatever that means
for your particular application) - only until it's running. There's a good
reason for this.
The problem of waiting for a database (for example) to be ready is really just
a subset of a much larger problem of distributed systems. In production, your
database could become unavailable or move hosts at any time. Your application
needs to be resilient to these types of failures.
To handle this, your application should attempt to re-establish a connection to
the database after a failure. If the application retries the connection,
it should eventually be able to connect to the database.
The best solution is to perform this check in your application code, both at
startup and whenever a connection is lost for any reason. However, if you don't
need this level of resilience, you can work around the problem with a wrapper
script:
- Use a tool such as [wait-for-it](https://github.com/vishnubob/wait-for-it)
or [dockerize](https://github.com/jwilder/dockerize). These are small
wrapper scripts which you can include in your application's image and will
poll a given host and port until it's accepting TCP connections.
Supposing your application's image has a `CMD` set in its Dockerfile, you
can wrap it by setting the entrypoint in `docker-compose.yml`:
version: "2"
services:
web:
build: .
ports:
- "80:8000"
depends_on:
- "db"
entrypoint: ./wait-for-it.sh db:5432
db:
image: postgres
- Write your own wrapper script to perform a more application-specific health
check. For example, you might want to wait until Postgres is definitely
ready to accept commands:
#!/bin/bash
set -e
host="$1"
shift
cmd="$@"
until psql -h "$host" -U "postgres" -c '\l'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done
>&2 echo "Postgres is up - executing command"
exec $cmd
You can use this as a wrapper script as in the previous example, by setting
`entrypoint: ./wait-for-postgres.sh db`.
## Compose documentation
- [Installing Compose](install.md)
- [Get started with Django](django.md)
- [Get started with Rails](rails.md)
- [Get started with WordPress](wordpress.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

View file

@ -10,88 +10,133 @@ weight=6
<![end-metadata]-->
# Quickstart: Compose and WordPress
# Quickstart: Docker Compose and WordPress
You can use Compose to easily run WordPress in an isolated environment built
with Docker containers.
You can use Docker Compose to easily run WordPress in an isolated environment built
with Docker containers. This quick-start guide demonstrates how to use Compose to set up and run WordPress. Before starting, you'll need to have
[Compose installed](install.md).
## Define the project
First, [Install Compose](install.md) and then download WordPress into the
current directory:
1. Create an empty project directory.
$ curl https://wordpress.org/latest.tar.gz | tar -xvzf -
You can name the directory something easy for you to remember. This directory is the context for your application image. The directory should only contain resources to build that image.
This will create a directory called `wordpress`. If you wish, you can rename it
to the name of your project.
This project directory will contain a `Dockerfile`, a `docker-compose.yaml` file, along with a downloaded `wordpress` directory and a custom `wp-config.php`, all of which you will create in the following steps.
Next, inside that directory, create a `Dockerfile`, a file that defines what
environment your app is going to run in. For more information on how to write
Dockerfiles, see the
[Docker user guide](https://docs.docker.com/engine/userguide/dockerimages/#building-an-image-from-a-dockerfile) and the
[Dockerfile reference](https://docs.docker.com/engine/reference/builder/). In
this case, your Dockerfile should be:
2. Change directories into your project directory.
FROM orchardup/php5
ADD . /code
For example, if you named your directory `my_wordpress`:
This tells Docker how to build an image defining a container that contains PHP
and WordPress.
$ cd my-wordpress/
Next you'll create a `docker-compose.yml` file that will start your web service
and a separate MySQL instance:
3. Create a `Dockerfile`, a file that defines the environment in which your application will run.
version: '2'
services:
web:
build: .
command: php -S 0.0.0.0:8000 -t /code
ports:
- "8000:8000"
depends_on:
- db
volumes:
- .:/code
db:
image: orchardup/mysql
environment:
MYSQL_DATABASE: wordpress
For more information on how to write Dockerfiles, see the [Docker Engine user guide](https://docs.docker.com/engine/userguide/dockerimages/#building-an-image-from-a-dockerfile) and the [Dockerfile reference](https://docs.docker.com/engine/reference/builder/).
A supporting file is needed to get this working. `wp-config.php` is
the standard WordPress config file with a single change to point the database
configuration at the `db` container:
In this case, your Dockerfile should include these two lines:
<?php
define('DB_NAME', 'wordpress');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', "db:3306");
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');
FROM orchardup/php5
ADD . /code
define('AUTH_KEY', 'put your unique phrase here');
define('SECURE_AUTH_KEY', 'put your unique phrase here');
define('LOGGED_IN_KEY', 'put your unique phrase here');
define('NONCE_KEY', 'put your unique phrase here');
define('AUTH_SALT', 'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT', 'put your unique phrase here');
define('NONCE_SALT', 'put your unique phrase here');
This tells the Docker Engine daemon how to build an image defining a container that contains PHP and WordPress.
$table_prefix = 'wp_';
define('WPLANG', '');
define('WP_DEBUG', false);
4. Create a `docker-compose.yml` file that will start your web service and a separate MySQL instance:
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');
version: '2'
services:
web:
build: .
command: php -S 0.0.0.0:8000 -t /code/wordpress/
ports:
- "8000:8000"
depends_on:
- db
volumes:
- .:/code
db:
image: orchardup/mysql
environment:
MYSQL_DATABASE: wordpress
require_once(ABSPATH . 'wp-settings.php');
5. Download WordPress into the current directory:
$ curl https://wordpress.org/latest.tar.gz | tar -xvzf -
This creates a directory called `wordpress` in your project directory.
6. Create a `wp-config.php` file within the `wordpress` directory.
A supporting file is needed to get this working. At the top level of the wordpress directory, add a new file called `wp-config.php` as shown. This is the standard WordPress config file with a single change to point the database configuration at the `db` container:
<?php
define('DB_NAME', 'wordpress');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', "db:3306");
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');
define('AUTH_KEY', 'put your unique phrase here');
define('SECURE_AUTH_KEY', 'put your unique phrase here');
define('LOGGED_IN_KEY', 'put your unique phrase here');
define('NONCE_KEY', 'put your unique phrase here');
define('AUTH_SALT', 'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT', 'put your unique phrase here');
define('NONCE_SALT', 'put your unique phrase here');
$table_prefix = 'wp_';
define('WPLANG', '');
define('WP_DEBUG', false);
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');
require_once(ABSPATH . 'wp-settings.php');
?>
7. Verify the contents and structure of your project directory.
<!--
Dockerfile
docker-compose.yaml
wordpress/
index.php
license.txt
readme.html
wp-activate.php
wp-admin/
wp-blog-header.php
wp-comments-post.php
wp-config-sample.php
wp-config.php
wp-content/
wp-cron.php
wp-includes/
wp-links-opml.php
wp-load.php
wp-login.php
wp-mail.php
wp-settings.php
wp-signup.php
wp-trackback.php
xmlrpc.php
-->
![WordPress files](images/wordpress-files.png)
### Build the project
With those four files in place, run `docker-compose up` inside your WordPress
directory and it'll pull and build the needed images, and then start the web and
database containers. If you're using [Docker Machine](https://docs.docker.com/machine/), then `docker-machine ip MACHINE_VM` gives you the machine address and you can open `http://MACHINE_VM_IP:8000` in a browser.
With those four new files in place, run `docker-compose up` from your project directory. This will pull and build the needed images, and then start the web and database containers.
If you're using [Docker Machine](https://docs.docker.com/machine/), then `docker-machine ip MACHINE_VM` gives you the machine address and you can open `http://MACHINE_VM_IP:8000` in a browser.
At this point, WordPress should be running on port `8000` of your Docker Host, and you can complete the "famous five-minute installation" as a WordPress administrator.
![Choose language for WordPress install](images/wordpress-lang.png)
![WordPress Welcome](images/wordpress-welcome.png)
## More Compose documentation