docker-compose
docker内容器之间是如何相互通信的?
docker网络的组织形式
例如:我们先启动一个nginx的容器,查看其在docker中的ip
然后我们在启动一个其他容器,访问刚才nginx容器的ip
这种方式的缺点比较麻烦,在生成环境中是不可行的。我们需要登陆一台机器去查看其docker内容器的启动ip,然后在另一个在进入另一个容器内去配置要访问的容器的ip。
--link映射
将另一个容器的IP映射到本容器里,映射的方式是通过修改/etc/hosts文件。
docker run -d -p80:80 --name mynginx nginx
docker run -d -it --link mynginx:myng centos # --link会将mynginx的ip映射到myng上,在centos内容可以之间访问映射过来的参数myng # 这一点有些类似vue中父子组件传参,但有一点不同,见下图 docker exec -it c1597cf46d1e /bin/bash
当在centos容器中ping myng或mynginx时,它会自动解析为nginx容器的IP,myng和mynginx作为一个域名,会被解析为nginx容器的IP。
缺陷:
每次运行一个容器都要使用--link的方式指明比较麻烦,其次是启动的顺序必须由下而上。当迁移到其他机器时或重启时重新部署都比较繁琐,有没有一种方式可以将这些指令记录到一个文件里,进行统一的配置呢?那就时docker-compose。
docker-compose
安装
pip install docker-compose
异常
# [liuwei@localhost redis-cluster]$ docker-compose up -d ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running? If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
这是由于当前用户没有docker使用权限导致的,解决办法就是把当前用户加入docker组
# 1、如果还没有 docker group 就添加一个 sudo groupadd docker # 2、将用户加入该 group 内。然后退出并重新登录就生效啦。 sudo gpasswd -a ${USER} docker # 3、重启 docker 服务 sudo service docker restart # 4、切换当前会话到新 group 或者重启 X 会话 newgrp - docker # 注意:最后一步是必须的,否则因为 groups 命令获取到的是缓存的组信息,刚添加的组信息未能生效,所以 docker images 执行时同样有错。
制作docker-compose.yml文件
version: "3" services: # 指定服务 web: # 镜像名称,docker compose会使用路径名_镜像名_num的方式构建容器的镜像名 container_name: explorer-container # 容器名称 build: demo #image: imagename:tag # 如果有之间指定,没有可以使用上面build新构建一个 restart: always # 容器停了会被重启。 privileged: true ports: # 相当于-p参数 - "8000:8000" command: uwsgi --ini /demo/uwsgi.ini # 相当于启动后加的启动参数 volumes: # 相当于-v参数 - ./demo:/demo nginx: container_name: nginx-container restart: always depends_on: # depends_on可以让我们书写compose不必按照--link那样的顺序去书写我们的services,只要指定了depends_on,他会优先启动它依赖的镜像 - web links: # 相当于--link web:web,将上面web镜像启动的容器映射到nginx容器内部 - "web:web" # - web # 另一种书写方式 build: nginx ports: - "80:80" volumes: - ./nginx/data:/var/log/nginx - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf # - ./django/static:/code/static mysql: image: mysql:5.6 restart: always ports: - "3306:3306" environment: # 设置环境变量:MYSQL_ROOT_PASSWORD是mysql启动必须配置的参数 - MYSQL_ROOT_PASSWORD=123456
先来看一下nginx.conf的配置:
upstream django{ server web:8000; # 这里的web是个域名,就类似上面--link后面的参数 } server { listen 80 default_server; listen [::]:80 default_server; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { include /etc/nginx/uwsgi_params; uwsgi_connect_timeout 30; uwsgi_pass django; root /usr/share/nginx/html; index index.html index.htm; } location /static/ { alias /demo/explorerfront/dist/; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ .php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ .php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /.ht { # deny all; #} }
这里配置
upstream django{ server web:8000; # 这里的web是个域名,就类似上面--link后面的参数 }
又例如如果是使用php连接mysql而不是python:
<?php $servername = "mysql"; $username = "username"; $password = "password"; try { $conn = new PDO("mysql:host=$servername;", $username, $password); echo "连接成功"; } catch(PDOException $e) { echo $e->getMessage(); } ?>
为啥这里nginx里的server web:8000和php里设置$servername能被正确请求到?这是docker容器在通信时做的域名解析,也就是说:
http://web:8000 =[被docker容器解析]=> http://web镜像运行容器的ip:8000
http://mysql:3306/? =[被docker容器解析]=> http://mysql镜像运行容器的ip:3306/?
只要发现请求,docker容器都会去找里里面有没有镜像名,如果有就替换。
docker-compose基本命令
docker-compose up
docker-compose up [options] [--scale SERVICE=NUM...] [SERVICE...] 选项包括: -d 在后台运行服务容器 -no-color 不是有颜色来区分不同的服务的控制输出 -no-deps 不启动服务所链接的容器 --force-recreate 强制重新创建容器,不能与-no-recreate同时使用 –no-recreate 如果容器已经存在,则不重新创建,不能与–force-recreate同时使用 –no-build 不自动构建缺失的服务镜像 –build 在启动容器前构建服务镜像 –abort-on-container-exit 停止所有容器,如果任何一个容器被停止,不能与-d同时使用 -t, –timeout TIMEOUT 停止容器时候的超时(默认为10秒) –remove-orphans 删除服务中没有在compose文件中定义的容器
docker-compose ps
docker-compose ps [options] [SERVICE...]
列出项目中所有的容器
docker-compose stop
docker-compose stop [options] [SERVICE...] 选项包括 -t, –timeout TIMEOUT 停止容器时候的超时(默认为10秒) docker-compose stop 停止正在运行的容器,可以通过docker-compose start 再次启动
docker-compose -h
docker-compose -h
查看帮助
docker-compose down
docker-compose down [options] 停止和删除容器、网络、卷、镜像。 选项包括: –rmi type,删除镜像,类型必须是:all,删除compose文件中定义的所有镜像;local,删除镜像名为空的镜像 -v, –volumes,删除已经在compose文件中定义的和匿名的附在容器上的数据卷 –remove-orphans,删除服务中没有在compose中定义的容器 docker-compose down 停用移除所有容器以及网络相关
docker-compose logs
docker-compose logs [options] [SERVICE...] 查看服务容器的输出。默认情况下,docker-compose将对不同的服务输出使用不同的颜色来区分。可以通过–no-color来关闭颜色。 docker-compose logs 查看服务容器的输出 -f 跟踪日志输出
docker-compose build
docker-compose build [options] [--build-arg key=val...] [SERVICE...] 构建(重新构建)项目中的服务容器。 选项包括: –compress 通过gzip压缩构建上下环境 –force-rm 删除构建过程中的临时容器 –no-cache 构建镜像过程中不使用缓存 –pull 始终尝试通过拉取操作来获取更新版本的镜像 -m, –memory MEM为构建的容器设置内存大小 –build-arg key=val为服务设置build-time变量 服务容器一旦构建后,将会带上一个标记名。可以随时在项目目录下运行docker-compose build来重新构建服务
docker-compose pull
docker-compose pull [options] [SERVICE...] 拉取服务依赖的镜像。 选项包括: –ignore-pull-failures,忽略拉取镜像过程中的错误 –parallel,多个镜像同时拉取 –quiet,拉取镜像过程中不打印进度信息 docker-compose pull 拉取服务依赖的镜像
docker-compose restart
docker-compose restart [options] [SERVICE...] 重启项目中的服务。 选项包括: -t, –timeout TIMEOUT,指定重启前停止容器的超时(默认为10秒) docker-compose restart 重启项目中的服务
docker-compose rm
docker-compose rm [options] [SERVICE...] 删除所有(停止状态的)服务容器。 选项包括: –f, –force,强制直接删除,包括非停止状态的容器 -v,删除容器所挂载的数据卷 docker-compose rm 删除所有(停止状态的)服务容器。推荐先执行docker-compose stop命令来停止容器。
docker-compose start
docker-compose start [SERVICE...] docker-compose start 启动已经存在的服务容器。
docker-compose run
docker-compose run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...] 在指定服务上执行一个命令。 docker-compose run ubuntu ping www.baidu.com 在指定容器上执行一个ping命令。
docker-compose scale
docker-compose scale web=3 db=2
设置指定服务运行的容器个数。通过service=num的参数来设置数量
docker-compose pause
docker-compose pause [SERVICE...]
暂停一个服务容器
docker-compose kill
docker-compose kill [options] [SERVICE...] 通过发送SIGKILL信号来强制停止服务容器。 支持通过-s参数来指定发送的信号,例如通过如下指令发送SIGINT信号: docker-compose kill -s SIGINT
docker-compose config
docker-compose config [options] 验证并查看compose文件配置。 选项包括: –resolve-image-digests 将镜像标签标记为摘要 -q, –quiet 只验证配置,不输出。 当配置正确时,不输出任何内容,当文件配置错误,输出错误信息 –services 打印服务名,一行一个 –volumes 打印数据卷名,一行一个
docker-compose create
docker-compose create [options] [SERVICE...] 为服务创建容器。 选项包括: –force-recreate:重新创建容器,即使配置和镜像没有改变,不兼容–no-recreate参数 –no-recreate:如果容器已经存在,不需要重新创建,不兼容–force-recreate参数 –no-build:不创建镜像,即使缺失 –build:创建容器前 ,生成镜像
docker-compose exec
docker-compose exec [options] SERVICE COMMAND [ARGS...] 选项包括: -d 分离模式,后台运行命令。 –privileged 获取特权。 –user USER 指定运行的用户。 -T 禁用分配TTY,默认docker-compose exec分配TTY。 –index=index,当一个服务拥有多个容器时,可通过该参数登陆到该服务下的任何服务,例如:docker-compose exec –index=1 web /bin/bash ,web服务中包含多个容器
docker-compose port
docker-compose port [options] SERVICE PRIVATE_PORT 显示某个容器端口所映射的公共端口。 选项包括: –protocol=proto,指定端口协议,TCP(默认值)或者UDP –index=index,如果同意服务存在多个容器,指定命令对象容器的序号(默认为1)
docker-compose push
docker-compose push [options] [SERVICE...]
推送服务依的镜像。
选项包括:
–ignore-push-failures 忽略推送镜像过程中的错误
docker-compose stop
docker-compose stop [options] [SERVICE...]
停止运行的容器
docker-compose uppause
docker-compose unpause [SERVICE...]
恢复处于暂停状态中的服务。
docker-compose.yml配置参数说明
#系统变量 $PWD : 当前目录 #注意:YAML布尔值(true,false,yes,no,on,off)必须用引号括起来,以便解析器将它们解释为字符串。 #字典时 environment: SHOW: 'true' 数组时 environment: - SHOW=true
#版本号 version: "2.1" # 指定创建的虚拟网络数量 # 作用:通过不同的虚拟网络实现了容器网络之间的隔离,从而在最大程度上去保护后端网络的安全。 #networks: # mynet: # driver: bridge # mynet1: # 重用的代码模板 # 模板的定义必须以 x- 开头 x-logging: # 以 & 开头的字符串为模板命名 # 以 * 加上模板的名称引用模板 &default-logging driver: json-file options: max-size: "200k" max-file: "10" # 定义全局挂载卷 volumes: test_1.thinking.com: test_2.thinking.com: # 服务 services: #服务名称 todo: # 构建镜像 build: # 指定dockerfile的上下文路径(相对当前docker-compose.yml的位置) # 包含Dockerfile文件的目录路径,或者是git仓库的URL。 # 当提供的值是相对路径时,它被解释为相对于当前compose文件的位置。 # 该目录也是发送到Docker守护程序构建镜像的上下文。 context: . # Dockerfile的文件名称 dockerfile: Dockerfile-todo args: # 变量 buildno: 1 password: secret # Dockerfile里面可使用的参数变量 # Dockerfile: # ARG buildno # ARG password # RUN echo "Build number: $buildno" # RUN script-requiring-password.sh "$password" # 镜像名 : 仓库/标签:版本 image: zhanyang/todo-demo:1.0.0 # 依赖(以指定顺序启动) depends_on: mysql: condition: service_healthy # 指定一个自定义容器名称,而不是生成的默认名称。 # 由于Docker容器名称必须是唯一的,因此如果指定了自定义名称,则无法将服务扩展到多个容器。 container_name: todo # 卷挂载路径设置。 # 可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro) # 挂载数据卷的默认权限是读写(rw),可以通过ro指定为只读。 volumes: # 只需指定一个路径,让引擎创建一个卷 - /var/lib/mysql # 指定绝对路径映射 - /opt/data:/var/lib/mysql # 相对于当前compose文件的相对路径 - ./cache:/tmp/cache # 用户家目录相对路径 - ~/configs:/etc/configs/:ro # 命名卷 - datavolume:/var/lib/mysql # 使用全局挂载卷 - test_1.thinking.com:/test:rw # 指定日志驱动为 json-file,存储日志的最大文件 size 为 200k,最多存储 10 这样大的文件。 # logging支持很多driver,而每一个driver对应的options都不一样 # docker inspect -f {{.HostConfig.LogConfig}} lnmp-nginx # result:{json-file map[max-file:10 max-size:2000k]} # docker info |grep 'Logging Driver' # result:Logging Driver: json-file # 其他:https://docs.docker.com/engine/admin/logging/overview/ logging: driver: "json-file" options: max-size: "200k" max-file: "10" # 指定使用的虚拟网络 networks: # - mynet # 覆盖容器启动后默认执行的命令。 # 该命令也可以是一个类似于dockerfile的列表:command: ["bundle", "exec", "thin", "-p", "3000"] command: bundle exec thin -p 3000 # may command: ["/usr/local/nginx/sbin/nginx"] # or command: bash start.sh # 链接到另一个服务中的容器。 请指定服务名称和链接别名(SERVICE:ALIAS),或者仅指定服务名称。 # 实际是通过设置/etc/hosts的域名解析,从而实现容器间的通信。 # 故可以像在应用中使用localhost一样使用服务的别名链接其他容器的服务,前提是多个服务容器在一个网络中可路由联通 # links也可以起到和depends_on相似的功能,即定义服务之间的依赖关系,从而确定服务启动的顺序 links: - db - db:database - redis # 链接到docker-compose.yml 外部的容器,甚至并非 Compose 管理的容器。参数格式跟 links 类似。 external - redis_1 - project_db_1:mysql - project_db_1:postgresql # 暴露端口,但不映射到宿主机,只被连接的服务访问。 仅可以指定内部端口为参数 expose: - "3000" - "8000" # 暴露端口信息。使用宿主:容器 (HOST:CONTAINER)格式或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。 ports: - "3000" - "3000-3005" - "8000:8000" - "9090-9091:8080-8081" - "49100:22" - "127.0.0.1:8001:8001" - "127.0.0.1:5000-5010:5000-5010" - "6060:6060/udp" # v3.2中ports的长格式的语法允许配置不能用短格式表示的附加字段。 ports: - target: 80 #容器内的端口 published: 8080 #物理主机的端口 protocol: tcp #端口协议(tcp或udp) mode: host #host 和ingress 两总模式,host用于在每个节点上发布主机端口,ingress 用于被负载平衡的swarm模式端口。 # no是默认的重启策略,在任何情况下都不会重启容器。 restart: "no" # 指定为always时,容器总是重新启动。 restart: always # 如果退出代码指示出现故障错误,则on-failure将重新启动容器。 restart: on-failure restart: unless-stopped # pid 将PID模式设置为主机PID模式。 # 这就打开了容器与主机操作系统之间的共享PID地址空间。 # 使用此标志启动的容器将能够访问和操作裸机的命名空间中的其他容器,反之亦然。 # 即打开该选项的容器可以相互通过进程 ID 来访问和操作。 pid: "host" # 配置 DNS 服务器。可以是一个值,也可以是一个列表。 dns: 8.8.8.8 dns: - 8.8.8.8 - 9.9.9.9 # 自定义搜索域 dns_search: example.com dns_search: - dc1.example.com - dc2.example.com # 覆盖Dockerfile中的entrypoint,用法同Dockerfile中的用法 entrypoint: ["/usr/local/nginx/sbin/nginx","-g","daemon off;"] # 添加环境变量。 你可以使用数组或字典两种形式。 # 任何布尔值; true,false,yes,no需要用引号括起来,以确保它们不被YML解析器转换为True或False。 environment: RACK_ENV: development SHOW: 'true' SESSION_SECRET: # 【注意】:如果你的服务指定了build选项,那么在构建过程中通过environment定义的环境变量将不会起作用。 # 将使用build的args子选项来定义构建时的环境变量。 environment: - RACK_ENV=development - SHOW=true - SESSION_SECRE # 1>将定义的变量编写在文件中,然后在yml文件中进行添加 env_file: .env env_file: - ./common.env - ./apps/web.env - /opt/secrets.env # 2>例如: # old: db: image: mysql ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: redhat MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress # new: db: image: mysql ports: - "3306:3306" env_file: ./mysql_env # 创建env_file文件在当前目录mysql_env MYSQL_ROOT_PASSWORD=redhat MYSQL_DATABASE=wordpress MYSQL_USER=wordpress MYSQL_PASSWORD=wordpress3 # 添加hostname映射,类似于docker cli下面的--add-host extra_hosts: - "www.hcstart.com:192.168.101.14" # 配置一个检查去测试服务中的容器是否运行正常 # 具体: https://docs.docker.com/engine/reference/builder/#healthcheck # 查看healthcheck的状态输出 : docker inspect lnmp-nginx healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 1m30s timeout: 10s retries: 3 # labels:添加元数据到container中,查看现有容器的labels: # docker inspect -f {{.Config.Labels}} lnmp-nginx # lnmp-nginx :容器名 labels: com.example.description: "Accounting webapp" com.example.department: "Finance" com.example.label-with-empty-value: "" labels: - "com.example.description=Accounting webapp" - "com.example.department=Finance" - "com.example.label-with-empty-value" # 在容器中设置内核参数 sysctls: net.core.somaxconn: 1024 net.ipv4.tcp_syncookies: 0 sysctls: - net.core.somaxconn=1024 - net.ipv4.tcp_syncookies=0 mysql: environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: tododb MYSQL_USER: user MYSQL_PASSWORD: pass build: context: . dockerfile: Dockerfile-mysql image: zhanyang/mysql:5.6 container_name: mysql # 以 * 加上模板的名称引用模板 使用全局自定义模板 logging: *default-logging # 指定使用的虚拟网络 networks: # - mynet1