Get Started

Kesa...大约 4 分钟dockerdocker compose

Get Started

本节代码参见compose-test

1. Prerequisites

首先安装 Docker Compose ,

$ pacman -S docker-compose

2. Setup

Define the application dependencies

  1. Create a directory for the proejct:

    import time
    
    import redis
    from flask import Flask
    
    app = Flask(__name__)
    cache = redis.Redis(host='redis', port=6379)
    
    def get_hit_count():
        retries = 5
        while True:
            try:
                return cache.incr('hits')
            except redis.exceptions.ConnectionError as exc:
                if retries == 0:
                    raise exc
                retries -= 1
                time.sleep(0.5)
    
    @app.route('/')
    def hello():
        count = get_hit_count()
        return 'Hello World! I have been seen {} times.\n'.format(count)
    
  2. Create a file app.py :

    import time
    
    import redis
    from flask import Flask
    
    app = Flask(__name__)
    cache = redis.Redis(host='redis', port=6379)
    
    def get_hit_count():
        retries = 5
        while True:
            try:
                return cache.incr('hits')
            except redis.exceptions.ConnectionError as exc:
                if retries == 0:
                    raise exc
                retries -= 1
                time.sleep(0.5)
    
    @app.route('/')
    def hello():
        count = get_hit_count()
        return 'Hello World! I have been seen {} times.\n'.format(count)
    

    In this example, redis is the hostname of the redis container on the application’s network. We use the default port for Redis, 6379.

    Handling transient errors

    Note the way the get_hit_count function is written. This basic retry loop lets us attempt our request multiple times if the redis service is not available. This is useful at startup while the application comes online, but also makes our application more resilient if the Redis service needs to be restarted anytime during the app’s lifetime. In a cluster, this also helps handling momentary connection drops between nodes.

  3. Create file requirements.txt :

    flask
    redis
    

3. Create a Dockerfile

Write a Dockerfile that builds a Docker image. The imge contains all the dependencies the Python application requires, including Python iteself.

In project directory, create a file Dockerfile:

FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]

This tells Docker to:

  • Build an image starting with Python 3.7 image
  • Set the working directory to /code (会自动创建)
  • Set environment variables used by the flask command
  • Install gcc and other dependencies
  • Copy requirements.txt and install the Python dependencies
  • Add metadata to the image to describe that the container is listening on port 5000
  • Copy the current directory . in the project to the workdir . in the image
  • Set the default command for the container to flask run

4. Define services in a Compose file

Create a file docker-compose.yml

version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

This Compose file defines two services: web and redis

4.1 Web service

The web service uses an image that’s build from the Dockerfile in the current directory. It then binds the container and the host machine to the exposed port 5000 (the default port for the flask web server)

4.2 Redis service

The redis service uses a public Redis imges redis:alpine

5. Build and run your app with Compose

  1. From the project directory, start up app by running docker compose up

    $ docker compose up 
    

    Compose pull a Redis iamge, builds an image for you code, and starts the services you defined. In this case, the code is statically copied into the image at build time

  2. Use curl to test

    $ curl http://localhost:5000/
    Hello World! I have been seen 3 times.
    
  3. Switch to another terminal window, and type docker image ls

    $ docker image ls
    REPOSITORY                       TAG          IMAGE ID       CREATED             SIZE
    docker-compose-get-started_web   latest       da30493291c0   About an hour ago   183MB
    python                           3.7-alpine   a1034fd13493   2 weeks ago         41.8MB
    redis                            alpine       3900abf41552   2 weeks ago         32.4MB
    
  4. Stop the application, either by running docker-compose down from within your project directory in the second terminal, or by hitting CTRL+C in the original terminal where you started the app

    $ docker compose down
    [+] Running 3/3
     ⠿ Container docker-compose-get-started-web-1    Removed                     10.3s
     ⠿ Container docker-compose-get-started-redis-1  Removed                      0.2s
     ⠿ Network docker-compose-get-started_default    Removed                      0.1s
    

可以看到使用 docker compose down 之后会将 containernetwork 删除,若使用 CTRL+C 只会删除容器而网络将不会被删除

6. Edit the Compose file to add a bind mount

Edit docker-compose.yml ito add a bind mount for the web service:

version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
    environment:
      FLASK_ENV: development
  redis:
    image: "redis:alpine"

The volumes key mounts the project directory on the host to /code inside the container, allowing you to modify the code on the fly, without having to rebuild the image. The environment key sets the FLASK_NEW environment variable, which tells flask run to run in development mode and reload the code on change. This mode should only be used in development

7. Re-build and run the app with Compose

From project directory, run docker compose up

$ docker compose up

8. Update the application

Because the application code is now mounted into the container using a volume, you can make changes to its code and see the changes instantly, without having to rebuild the image.

Change the greeting in app.py and save it. For example, change the Hello World! message to Hello from Docker!:

return 'Hello from Docker! I have been seen {} times.\n'.format(count)
$ curl 'http://localhost:5000'
Hello from Docker! I have been seen 1 times.

9. Experiment with some other commands

You can pass the -d flag (detached mode ) to docker compose up and use docker compose ps to see what is currently running:

$ docker compose up -d 
# ...
$ docker compose ps
NAME                                 COMMAND                  SERVICE             STATUS              PORTS
docker-compose-get-started-redis-1   "docker-entrypoint.s…"   redis               running             6379/tcp
docker-compose-get-started-web-1     "flask run"              web                 running             0.0.0.0:5000->5000/tcp, :::5000->5000/tcp

The docker compose run command allows you to run one-off commands for your services. For example, to see what environment variables are available to the web service

$ docker compose run web env

If you started Compose with docker compose up -d, stop your services once you’ve finished with them

$ docker compose stop

You can bring everything down, removing the containers entirely, with the down command. Pass --volumes to also remove the data volume used by the Redis container

$ docker compose down --volumes

Reference

  1. Get started with Docker Composeopen in new window
上次编辑于:
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.2