Docker Compose入门 简介 一般一个宿主机中会生成多个容器,容器与容器之间需要协调工作,有时多个容器之间也需要进行环境的隔离,而Docker Compose就是用来定义和运行多个容器的工具。可以通过一个yaml文件来配置应用程序的服务,并通过命令来管理所有服务的生命周期。
安装步骤 一般可以在Compose repository release page on GitHub 获取到最新版的Docker Compse。
下载 执行以下命令:
1 sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
如果需要其他版本的Docker Compse,只需要把命令中的1.29.2
替换成需要的版本即可。
如果curl安装有问题,可以参照Alternative Install Options 进行安装。
赋予执行权限 1 sudo chmod +x /usr/local/bin/docker-compose
检查是否安装成功 1 2 > docker-compose --version docker-compose version 1.29.2, build 5becea4c
如何使用 基本配置 在docker compose下,存在服务的概念,一个compose配置可以由多个服务来组成,参考如下yaml配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 version: "3.9" services: db_mysql: image: mysql restart: always container_name: my-mysql ports: - 10001 :3306 environment: MYSQL_ROOT_PASSWORD: new_password_xxx command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - /usr/local/docker/mysql/data/:/var/lib/mysql - /usr/local/docker/mysql/conf.d:/etc/mysql/conf.d redis: image: redis hostname: redis-server restart: always container_name: my-redis ports: - 10002 :6379 command: redis-server /etc/redis/redis.conf --appendonly yes volumes: - /usr/local/docker/redis/conf/redis.conf:/etc/redis/redis.conf nginx: image: nginx restart: always container_name: my-nginx ports: - 80 :80 volumes: - /usr/local/docker/nginx/nginx.conf:/etc/nginx/nginx.conf redis-commander: container_name: redis-commander hostname: redis-commander image: rediscommander/redis-commander:latest restart: always environment: - REDIS_HOSTS=local:redis-server:6379 ports: - 11002 :8081
存在一个services节点,该节点下定义了三个服务。每个服务会对应到一个镜像,当执行docker-compose up
之后,会根据每个服务对应的镜像,生成对应的容器。服务的名称可以自行定义,无强制要求。
在yaml所在目录下执行
1 2 3 4 5 > docker-compose up -d Creating network "docker-compose_default" with the default driver Creating my-mysql ... done Creating my-nginx ... done Creating my-redis ... done
up
为创建并启动所有容器,-d
表示守护态运行。这里不指定配置文件名称,则默认当前目录下的名为docker-compose.yml
的文件。不指定项目名称,则默认该配置文件所在的目录名称作为项目名称。
可以看到配置文件所定义的所有服务均正常启动。
1 2 3 4 5 > docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ea6c7d60903d redis "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:10002->6379/tcp, :::10002->6379/tcp my-redis 49062f5891e7 nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp my-nginx d63a6ed103f5 mysql "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 33060/tcp, 0.0.0.0:10001->3306/tcp, :::10001->3306/tcp my-mysql
常用命令 对于docker-compose
有如下选项。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Commands: build Build or rebuild services config Validate and view the Compose file create Create services down Stop and remove resources 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 version information and quit
讲一些比较常用的。
up
命令,用于创建并启动compose项目。
然后就是start
、stop
等,仅进行启动和停止服务。
如果是执行down
命令,在停止所有服务容器的同时,也会删除所有容器以及网络。
如果改变了一个服务的Dockerfile或者构建目录的内容,可以使用build
命令对其进行重建。
ps
的用法都差不多,查看所有正在运行的容器。
每个命令具体用法,还是要参见--help
。
容器与容器间的访问 一般创建容器 当docker创建一个容器时,会将它纳入一个网络。如果是单独创建容器,则会纳入默认的bridge
网络中(默认为bridge模式),如:
新建一个tomcat容器:
1 2 > docker pull tomcat > docker run --name my-tomcat --rm -p 8080:8080 -d tomcat
通过dockers network
命令查看
1 2 3 4 5 6 > docker network ls NETWORK ID NAME DRIVER SCOPE 3d18fe44fe65 bridge bridge local de7157fb3e93 docker-compose_default bridge local da3cd2189967 host host local 098d7dd513d5 none null local
可以看到,有一个name为brideg
的网络,查看详细信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 > docker network inspect bridge [ { "Name": "bridge", "Id": "3d18fe44fe65f8d4f370adc558ce41a92897ce58288fa2f16aa2787dcebd9e0c", "Created": "2021-07-11T17:04:49.64883344+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "e42b6c1b108d756cc266cb29d0f6d779c396d62fbc5eef556ad42356ec275b9e": { "Name": "my-tomcat", "EndpointID": "00e0c410554cb08d4c4c65861d844fc98297f32ca9be628087c934f44bccb82b", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
其中Containers有刚刚创建的my-tomcat
容器。
docker-compose创建的网络 在使用docker-compose
创建一个项目后,会将该项目中所有的服务(services)都纳入到同一个网络当中,默认的网络名称为项目名加上_default
,如上面的docker-compose_default
网络。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 > docker network inspect docker-compose_default [ { "Name": "docker-compose_default", "Id": "de7157fb3e937908299c17cd3d21380a5dca2960a93bcb9da0ed392f5a4d74d7", "Created": "2021-08-01T10:46:49.281728229+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.19.0.0/16", "Gateway": "172.19.0.1" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "49062f5891e7d12eccbefb19875bcc0bd16b8e79906abb4952bb0420c1d09d72": { "Name": "my-nginx", "EndpointID": "c3e9773c7cb20222762f37784a24d35912e48edaf332408f61c6be19033382c2", "MacAddress": "02:42:ac:13:00:04", "IPv4Address": "172.19.0.4/16", "IPv6Address": "" }, "d63a6ed103f525148402f57919648e2e7caadd43d51a36597b058a7ecfedf8e4": { "Name": "my-mysql", "EndpointID": "391283e8835fa8107c6eb95ef946ffabaff8daa9ac5f6325274224f40925cead", "MacAddress": "02:42:ac:13:00:03", "IPv4Address": "172.19.0.3/16", "IPv6Address": "" }, "ea6c7d60903ded82d4c26d5fa47cdcdb005eba94ff5ff825e65e3815e44aab88": { "Name": "my-redis", "EndpointID": "1dc8f641e6599117fbc9ba605a0940ed1f71b630646db2553670d64fd361d853", "MacAddress": "02:42:ac:13:00:02", "IPv4Address": "172.19.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": { "com.docker.compose.network": "default", "com.docker.compose.project": "docker-compose", "com.docker.compose.version": "1.29.2" } } ]
其中包含了我们创建的三个服务容器。
容器与容器间需要进行网络通信,使用的是CONTAINER_IP:CONTAINER_PORT
,而不是映射到宿主机的ip和端口。
举个例子,新加入一个服务到上面的docker-compose.yml中。
1 2 3 4 5 6 7 8 9 10 11 12 version: 3.9 services: redis-commander: container_name: redis-commander hostname: redis-commander image: rediscommander/redis-commander:latest restart: always environment: - REDIS_HOSTS=local:redis:6379 ports: - 11002 :8081
environment
需要配置redis容器的地址,这里使用local:redis:6379
,其中的redis
为compose中定义的服务名,通过服务名,docker可以自己获取该服务的当前ip。端口使用的是6379,而非映射的10002。
保存yml后,重新执行docker-compose up -d
,会更新有变化的容器。
1 2 3 4 5 6 7 8 9 10 11 12 13 > docker-compose up -d Pulling redis-commander (rediscommander/redis-commander:latest)... latest: Pulling from rediscommander/redis-commander 339de151aab4: Pull complete f732fa32fc61: Pull complete ef60bb667d5a: Pull complete 4f50fa5032a4: Pull complete Digest: sha256:19cd0c49f418779fa2822a0496c5e6516d0c792effc39ed20089e6268477e40a Status: Downloaded newer image for rediscommander/redis-commander:latest my-redis is up-to-date my-nginx is up-to-date Creating redis-commander ... Creating redis-commander ... done
访问11002端口,可以看到redis-commander已成功部署,并正常连接到了我们所配置的redis服务。