docker-compose 初体验

本贴最后更新于 2320 天前,其中的信息可能已经物是人非

概述

docker-compose,可以实现从 Dockerfile 来构建 docker 镜像。

安装

在 mac 下,默认已经安装了 docker-compose。其它环境下的安装见官方文档

Python web 应用示例

本小节实现一个 python web 应用,使用了 Flask 框架,保存点击数据到 redis 中。

准备工作

已经安装好了 Docker Engine 和 Docker Compose

设置

创建工程目录

$ mkdir composetest
$ cd composetest

创建 app.py 文件

内容如下

from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

@app.route('/')
def hello():
    count = redis.incr('hits')
    return 'Hello World! I have been seen {} times.\n'.format(count)

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

其中 redis 是本容器的主机名;Redis 服务使用默认端口 6379

创建 requirements.txt 文件

内容如下

flask
redis

编写 DockerFile

内容如下

FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

含义

    FROM python:3.4-alpine: 以Python 3.4镜像为基础来建立新镜像
    ADD . /code : 把当前.目录加入到镜像的/code目录下
    WORKDIR /code : 设置工作目录为 /code
    RUN pip install -r requirements.txt : 安装python依赖
    CMD ["python", "app.py"] : 启动的默认命令 python app.py

定义服务文件 docker-compose.yml

内容如下

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

定义了两个服务,web 和 redis.

其中 web 服务

  • 使用当前目录下的 Dockerfile 来生成
  • 将容器中的 5000 端口提供给外部的 5000 端口,其中 5000 端口为 Flask web 服务器的默认端口

redis 服务使用公开的 redis 镜像

生成和运行镜像

生成镜像

执行

docker-compose up

结果如下

[abeffect@fox composetest]$ docker-compose up
Building web
Step 1/5 : FROM python:3.4-alpine
3.4-alpine: Pulling from library/python
ab7e51e37a18: Pull complete
4a57a4e05b89: Pull complete
547e91589715: Pull complete
3a89af968cdb: Pull complete
1d882d2fb1c0: Pull complete
Digest: sha256:e716e8ca57060b881433ebcfe72b8c2f81c2d9c05b02b868c6540ff80400c9cd
Status: Downloaded newer image for python:3.4-alpine
 ---> ec2a8f24cd3f
Step 2/5 : ADD . /code
 ---> e15132d21a7f
Step 3/5 : WORKDIR /code
 ---> ba3d1a3f3c9d
Removing intermediate container 4af36b601af8
Step 4/5 : RUN pip install -r requirements.txt
 ---> Running in 15668592c1cc
Collecting flask (from -r requirements.txt (line 1))
  Downloading Flask-0.12.2-py2.py3-none-any.whl (83kB)
Collecting redis (from -r requirements.txt (line 2))
  Downloading redis-2.10.6-py2.py3-none-any.whl (64kB)
Collecting itsdangerous>=0.21 (from flask->-r requirements.txt (line 1))
  Downloading itsdangerous-0.24.tar.gz (46kB)
Collecting Jinja2>=2.4 (from flask->-r requirements.txt (line 1))
  Downloading Jinja2-2.10-py2.py3-none-any.whl (126kB)
Collecting click>=2.0 (from flask->-r requirements.txt (line 1))
  Downloading click-6.7-py2.py3-none-any.whl (71kB)
Collecting Werkzeug>=0.7 (from flask->-r requirements.txt (line 1))
  Downloading Werkzeug-0.13-py2.py3-none-any.whl (311kB)
Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->flask->-r requirements.txt (line 1))
  Downloading MarkupSafe-1.0.tar.gz
Building wheels for collected packages: itsdangerous, MarkupSafe
  Running setup.py bdist_wheel for itsdangerous: started
  Running setup.py bdist_wheel for itsdangerous: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/fc/a8/66/24d655233c757e178d45dea2de22a04c6d92766abfb741129a
  Running setup.py bdist_wheel for MarkupSafe: started
  Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/88/a7/30/e39a54a87bcbe25308fa3ca64e8ddc75d9b3e5afa21ee32d57
Successfully built itsdangerous MarkupSafe
Installing collected packages: itsdangerous, MarkupSafe, Jinja2, click, Werkzeug, flask, redis
Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.13 click-6.7 flask-0.12.2 itsdangerous-0.24 redis-2.10.6
 ---> 1257635dcda5
Removing intermediate container 15668592c1cc
Step 5/5 : CMD python app.py
 ---> Running in 25cad534cd57
 ---> 42b4b60fdd57
Removing intermediate container 25cad534cd57
Successfully built 42b4b60fdd57
Successfully tagged composetest_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Pulling redis (redis:alpine)...
alpine: Pulling from library/redis
1160f4abea84: Pull complete
a8c53d69ca3a: Pull complete
2dbffccae30e: Pull complete
0a00d98b862d: Pull complete
6162f8e8bd54: Pull complete
ed931789deac: Pull complete
Digest: sha256:0153c5db97e5852b25c5c4715cf88cff9d9dfd8fef5c4c81df8b4dd1a984abc7
Status: Downloaded newer image for redis:alpine
Creating composetest_redis_1 ...
Creating composetest_web_1 ...
Creating composetest_redis_1
Creating composetest_web_1 ... done
Attaching to composetest_redis_1, composetest_web_1
redis_1  | 1:C 16 Dec 05:06:10.723 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 16 Dec 05:06:10.723 # Redis version=4.0.6, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 16 Dec 05:06:10.723 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 16 Dec 05:06:10.724 * Running mode=standalone, port=6379.
redis_1  | 1:M 16 Dec 05:06:10.724 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1  | 1:M 16 Dec 05:06:10.724 # Server initialized
redis_1  | 1:M 16 Dec 05:06:10.724 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1  | 1:M 16 Dec 05:06:10.724 * Ready to accept connections
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1    |  * Restarting with stat
web_1    |  * Debugger is active!
web_1    |  * Debugger PIN: 196-949-087

查看结果

打开浏览器 http://localhost:5000/,可见

Hello World! I have been seen 4 times.

查看新镜像

[abeffect@fox ~]$ docker image ls
REPOSITORY                                        TAG                 IMAGE ID            CREATED             SIZE
composetest_web                                   latest              42b4b60fdd57        5 minutes ago       92.9MB
[abeffect@fox ~]$ docker inspect 42b4b60fdd57
[
    {
        "Id": "sha256:42b4b60fdd574d18f27884f32edf2cc4449523eb97d1554661aec5e50fe1efd3",
        "RepoTags": [
            "composetest_web:latest"
        ],
        "RepoDigests": [],
        "Parent": "sha256:1257635dcda544e585de8b2ea1307ff0b7faf6a15c8ab90fc88aa1a6086d1cf0",
        "Comment": "",
        "Created": "2017-12-16T05:04:27.8917461Z",
        "Container": "25cad534cd57b81a9c6a06f298dd7b1a5c0191dc5f22abf9504fe7275648b627",
        "ContainerConfig": {
            "Hostname": "25cad534cd57",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "LANG=C.UTF-8",
                "GPG_KEY=97FC712E4C024BBEA48A61ED3A5CA953F73C700D",
                "PYTHON_VERSION=3.4.7",
                "PYTHON_PIP_VERSION=9.0.1"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"python\" \"app.py\"]"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:1257635dcda544e585de8b2ea1307ff0b7faf6a15c8ab90fc88aa1a6086d1cf0",
            "Volumes": null,
            "WorkingDir": "/code",
            "Entrypoint": null,
            "OnBuild": [],
            "Labels": {}
        },
        "DockerVersion": "17.09.0-ce",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "LANG=C.UTF-8",
                "GPG_KEY=97FC712E4C024BBEA48A61ED3A5CA953F73C700D",
                "PYTHON_VERSION=3.4.7",
                "PYTHON_PIP_VERSION=9.0.1"
            ],
            "Cmd": [
                "python",
                "app.py"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:1257635dcda544e585de8b2ea1307ff0b7faf6a15c8ab90fc88aa1a6086d1cf0",
            "Volumes": null,
            "WorkingDir": "/code",
            "Entrypoint": null,
            "OnBuild": [],
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 92857408,
        "VirtualSize": 92857408,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/e83123443e921e32993dd696e7695b379a294a18cdef437eceb9357528495ea5/diff:/var/lib/docker/overlay2/9cfaa5ec27e127277ee46b31b4dec42ead3ee226d78a18d4e73d790afdb36192/diff:/var/lib/docker/overlay2/c5322d8fc626f222705ca47245659fb61a8425cb19cae870313816a6f7cdd795/diff:/var/lib/docker/overlay2/a0973b7fa22766473abcba4de270ca158fe7a880edfbeb9e951bd8df7e092cdc/diff:/var/lib/docker/overlay2/4fa6628eb56d3084ca7df065efcbd67da2a28830a88a21d8f4be4ce0ac329b1a/diff:/var/lib/docker/overlay2/fc1d51ffe7967f8159ed2d2d7008a32b2d106ddbf6b87f4fccadd2e3e16fae5c/diff",
                "MergedDir": "/var/lib/docker/overlay2/ff7f62d0dea47792506e149a63e87b79b545835be28cb176256df6d0f11a56a8/merged",
                "UpperDir": "/var/lib/docker/overlay2/ff7f62d0dea47792506e149a63e87b79b545835be28cb176256df6d0f11a56a8/diff",
                "WorkDir": "/var/lib/docker/overlay2/ff7f62d0dea47792506e149a63e87b79b545835be28cb176256df6d0f11a56a8/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:52a5560f4ca0b62c53985258faceddc20afe53fca394aec8a32083e01659d9fd",
                "sha256:7c5ea328fb338eacb5da19231dff14cfeb5f4048541efd160ecd3f0351862124",
                "sha256:c30b37dd392440c1c27a25382477535de1d11d939eb34c49b23868f11b6d706b",
                "sha256:97291ed7e0ce205b5bc6c47668975b75dab976f07748dd7002f93c54a7b5c74d",
                "sha256:8348954981b10ddde61e6f520992d54f3b2847a520330ebcbd95cbb01d0d5b50",
                "sha256:bd34a5638bcc4c1b68420ee40d46e8844c0d12657eb9ab7720aae3af93a5b437",
                "sha256:24edd138c6481e9a541537e3740d205db7bd285f4f00ad02622a1ddb95ff69dd"
            ]
        },
        "Metadata": {
            "LastTagTime": "2017-12-16T05:04:28.0303435Z"
        }
    }
]

停止应用

docker-compose down

或者

Ctrl+C

Gracefully stopping... (press Ctrl+C again to force)
Stopping composetest_web_1   ... done
Stopping composetest_redis_1 ... done

增加一个 bind 点

修改 docker-compose.yml 文件,增加一个 bind 点。

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
  redis:
    image: "redis:alpine"

volumes 参数将当前目录挂载到容器的 code 目录下,实现可以动态修改 code 目录内容,而不用重新生成镜像。

重新生成镜像

[abeffect@fox composetest]$ docker-compose up
Recreating composetest_web_1 ...
Starting composetest_redis_1 ...
Starting composetest_redis_1
Recreating composetest_web_1 ... done
Attaching to composetest_redis_1, composetest_web_1
redis_1  | 1:C 16 Dec 05:46:49.230 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 16 Dec 05:46:49.230 # Redis version=4.0.6, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 16 Dec 05:46:49.230 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 16 Dec 05:46:49.231 * Running mode=standalone, port=6379.
redis_1  | 1:M 16 Dec 05:46:49.231 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1  | 1:M 16 Dec 05:46:49.231 # Server initialized
redis_1  | 1:M 16 Dec 05:46:49.231 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1  | 1:M 16 Dec 05:46:49.231 * DB loaded from disk: 0.000 seconds
redis_1  | 1:M 16 Dec 05:46:49.231 * Ready to accept connections
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1    |  * Restarting with stat
web_1    |  * Debugger is active!
web_1    |  * Debugger PIN: 196-949-087

更新应用

  1. 修改 app.py 文件,将 return 行的内容更改如下
return 'Hello from Docker! I have been seen {} times.\n'.format(count)

  1. 刷新浏览器,可见
Hello from Docker! I have been seen 13 times.

其它命令

  1. docker-compose up -d

后台运行参数 -d

[abeffect@fox composetest]$ docker-compose up -d
Starting composetest_web_1 ...
Starting composetest_redis_1 ...
Starting composetest_web_1
Starting composetest_web_1 ... done
  1. docker-compose ps
[abeffect@fox composetest]$ docker-compose ps
       Name                      Command               State           Ports
-------------------------------------------------------------------------------------
composetest_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp
composetest_web_1     python app.py                    Up      0.0.0.0:5000->5000/tcp
  1. docker-compose run web env

docker-compose run 参数,在容器外,运行容器内的命令

[abeffect@fox composetest]$ docker-compose run web env
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=c58f98dd0dc6
TERM=xterm
LANG=C.UTF-8
GPG_KEY=97FC712E4C024BBEA48A61ED3A5CA953F73C700D
PYTHON_VERSION=3.4.7
PYTHON_PIP_VERSION=9.0.1
HOME=/root
  1. docker-compose --help

查看其它命令

  1. docker-compose stop

停止由-d 参数启动的容器

[abeffect@fox composetest]$ docker-compose stop
Stopping composetest_web_1   ... done
Stopping composetest_redis_1 ... done
  1. docker-compose down --volumes

停止所有,删除 redis 的数据 volumes

[abeffect@fox composetest]$ docker-compose down --volumes
Removing composetest_web_run_6 ... done
Removing composetest_web_run_5 ... done
Removing composetest_web_run_4 ... done
Removing composetest_web_run_3 ... done
Removing composetest_web_run_2 ... done
Removing composetest_web_run_1 ... done
Removing composetest_web_1     ... done
Removing composetest_redis_1   ... done
Removing network composetest_default

到此,已经了解了 docker-compose 的基本运行.

常用指令

见 docker-compose 帮助

build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the Compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information

示例:

ps List containers

docker-compose ps

docker ps -a

config

docker-compose -f lnmp.yaml config

docker-compose -f lnmp.yaml config --services

docker-compose -f lnmp.yaml config --volumes

down:停止并删除容器、网络、镜像、数据卷

exec:在运行的容器中执行命令

images:列出镜像

参考

  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    492 引用 • 926 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...