curl localhost:3344 # 访问暴露的地址测试是否成功启动, 返回页面如下 # <!DOCTYPE html> # <html> # <head> # <title>Welcome to nginx!</title> # ... # <body> # <h1>Welcome to nginx!</h1> # <p>If you see this page, the nginx web server is successfully installed and # working. Further configuration is required.</p> # ... # <p><em>Thank you for using nginx.</em></p> # </body> # </html>
docker run -d -p 3355:8080 --name tomcat01 tomcat # 容器命名为 tomcat01 跑在 3355 端口 curl localhost:3355 # 访问测试, 访问失败 # <!doctype html>...</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists...</body></html>
docker volume rm $(docker volume ls -q) # 删除卷,准备实验环境
docker run -it -d --name myos01 mycentos # 启动自制容器作为父容器
docker volume ls # 两个挂载卷创建完毕 # DRIVER VOLUME NAME # local 8532efd6dabd0254bf5cec28de4df8225e4b633b91d83e13d80ba3ea97a9b314 <- volume01 # local b398a216526cfe3a52f71a92c383694f73b91900dbe57159c02ab63040078c21 <- volume02
docker build -t cmdtest . # Sending build context to Docker daemon 2.048 kB # Step 1/2 : FROM centos # ---> 300e315adb2f # Step 2/2 : CMD ls -al # ---> Running in e8e0790ae8f3 # ---> 513ebac8ebef # Removing intermediate container e8e0790ae8f3 # Successfully built 513ebac8ebef
docker run cmdtest # . # .. # .dockerenv # bin # ... # sys # tmp # usr # var
docker run cmdtest -l # 如果想要追加 `l` 给出 `ls -al` 的效果怎么办?直接在 run 后接参数会报错 # container_linux.go:235: starting container process caused "exec: \"-l\": executable file not found in $PATH" # /usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:235: starting container process caused "exec: \"-l\": executable file not found in $PATH".
docker exec -it tomcat03 ping tomcat02 # PING tomcat02 (172.17.0.3) 56(84) bytes of data. # 64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.077 ms # 64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.050 ms
docker exec -it tomcat02 ping tomcat03 # 但是反向是 ping 不通的!!? # ping: tomcat03: Name or service not known
docker network ls # 使用 docker network ls 查看当前网络配置 # NETWORK ID NAME DRIVER SCOPE # ceb0592c9055 bridge bridge local # 5ac97b2cf390 host host local # 03f71a7f47f1 none null local
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 4ccaa4545718 tomcat "catalina.sh run" 15 minutes ago Up 15 minutes 0.0.0.0:55004->8080/tcp tomcat03 # c5012b364397 tomcat "catalina.sh run" 17 minutes ago Up 17 minutes 0.0.0.0:55003->8080/tcp tomcat02 # 3bf7596cfde9 tomcat "catalina.sh run" About an hour ago Up About an hour 0.0.0.0:55002->8080/tcp tomcat01
docker network connect --help# 查看使用方式 # Usage: docker network connect [OPTIONS] NETWORK CONTAINER # Connect a container to a network # Options: # --alias strings Add network-scoped alias for the container # --driver-opt strings driver options for the network # --ip string IPv4 address (e.g., 172.30.100.104) # --ip6 string IPv6 address (e.g., 2001:db8::33) # --link list Add link to another container # --link-local-ip strings Add a link-local address for the container
172.38.0.13:6379> get a # 回到原来的终端进行 get 操作 # Error: Operation timed out # /data # # 默认直接从原来的 13 节点拿了,服务停了,回到了 11 节点的 data 目录,再通过 redis-cli -c 进去集群终端 get a 信息从 14 节点,备份节点返回
redis-cli -c 127.0.0.1:6379> get a # 从 log 可以看到值是从备份节点 14 拿到的 # -> Redirected to slot [15495] located at 172.38.0.14:6379 # "b"
# 查看映射地址 docker ps # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 0b4da52a4593 myspringapp "java -jar /app.jar …" 3 seconds ago Up 2 seconds 0.0.0.0:55010->8080/tcp spapp
# 访问测试 curl localhost:55010/hello # Hello from springboot.
Docker Compose
Dockerfile 单个容器,Docker Compose 定义运行多个容器
Using Compose is basically a three-step process:
Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
Run docker compose up and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up using the docker-compose binary.
重要概念:
服务 services, 容器,应用(web, redis…)
项目 project,一组关联的容器
安装
Mac 的 docker-compose 工具集是和客户端整合在一起的,所以不需要单独安装,直接可以使用
docker ps # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 621dc8726fe9 composetest_web "flask run" 8 minutes ago Up 8 minutes 0.0.0.0:5000->5000/tcp composetest_web_1 # 6945405369e2 redis:alpine "docker-entrypoint.s…" 8 minutes ago Up 8 minutes 6379/tcp composetest_redis_1
docker network ls # NETWORK ID NAME DRIVER SCOPE # 39a92d7cce05 bridge bridge local # f713400ac914 composetest_default bridge local <- compose 启动之后会创建一个对应的网络,和之前的 log 匹配
# Commands: # init Initialize a swarm # join Join a swarm as a node and/or manager # join-token Manage join tokens # leave Leave the swarm # unlock Unlock swarm # unlock-key Manage the unlock key # update Update the swarm
docker swarm init --help # Usage: docker swarm init [OPTIONS] # Initialize a swarm # Options: # --advertise-addr string Advertised address (format: <ip|interface>[:port]) # --autolock Enable manager autolocking (requiring an unlock key to start a stopped manager) # --cert-expiry duration Validity period for node certificates (ns|us|ms|s|m|h) (default 2160h0m0s) # --dispatcher-heartbeat duration Dispatcher heartbeat period (ns|us|ms|s|m|h) (default 5s) # --external-ca external-ca Specifications of one or more certificate signing endpoints # --force-new-cluster Force create a new cluster from current state # --help Print usage # --listen-addr node-addr Listen address (format: <ip|interface>[:port]) (default 0.0.0.0:2377) # --max-snapshots uint Number of additional Raft snapshots to retain # --snapshot-interval uint Number of log entries between Raft snapshots (default 10000) # --task-history-limit int Task history retention limit (default 5)
docker swarm init --advertise-addr 172.28.231.215 # 创建 swarm 集群,提供两个可用命令,一个用于添加 worker 节点,一个用于添加 manager 节点 # Swarm initialized: current node (abele1bkn04awsnvvfzj0dof2) is now a manager.
# To add a worker to this swarm, run the following command:
# To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
docker node ls # 显示集群节点状态 # ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS # abele1bkn04awsnvvfzj0dof2 * iZuf6brcie4578p0e13tg9Z Ready Active Leader
docker swarm join \ --token SWMTKN-1-2n1wgk8ws8ca2bz2kr5nkqefrngtizuum901cv7hmhgqnsjuc1-3gwzzivpm27xfqk8ddclf6fth \ 172.28.231.215:2377 # 挑选一个可用节点,作为一个 worker 节点加入 # This node joined a swarm as a worker.
docker node ls # 再次查看节点状态,节点加入成功 # ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS # 9xujdtp2c7dob2t1o704tgwvl iZuf6brcie4578p0e13tg8Z Ready Active # abele1bkn04awsnvvfzj0dof2 * iZuf6brcie4578p0e13tg9Z Ready Active Leader
docker swarm join-token manager # 生成 manager 节点 token # To add a manager to this swarm, run the following command: # docker swarm join \ # --token SWMTKN-1-2n1wgk8ws8ca2bz2kr5nkqefrngtizuum901cv7hmhgqnsjuc1-392uyq8gmjgp9dj484y8id8jq \ # 172.28.231.215:2377
docker swarm join \ > --token SWMTKN-1-2n1wgk8ws8ca2bz2kr5nkqefrngtizuum901cv7hmhgqnsjuc1-392uyq8gmjgp9dj484y8id8jq \ > 172.28.231.215:2377 # 挑选一个可用节点,作为 manager 节点加入集群 # This node joined a swarm as a manager.
docker node ls # manager 节点的主备节点互换了 # ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS # 9xujdtp2c7dob2t1o704tgwvl iZuf6brcie4578p0e13tg8Z Ready Active # abele1bkn04awsnvvfzj0dof2 * iZuf6brcie4578p0e13tg9Z Ready Active Reachable # qr1s9a3q7h3j8dw48juw1emg4 myvm01 Ready Active Leader # y1gs7gsyuwoefjvmw8d9eswrm iZuf6brcie4578p0e13tgaZ Ready Active
docker swarm leave # 选取一个 worker 节点,起开集群
docker node ls # manager 节点显示,上面的节点 down 了 # ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS # 9xujdtp2c7dob2t1o704tgwvl iZuf6brcie4578p0e13tg8Z Down Active # abele1bkn04awsnvvfzj0dof2 * iZuf6brcie4578p0e13tg9Z Ready Active Reachable # qr1s9a3q7h3j8dw48juw1emg4 myvm01 Ready Active Leader # y1gs7gsyuwoefjvmw8d9eswrm iZuf6brcie4578p0e13tgaZ Ready Active
docker swarm join \ --token SWMTKN-1-2n1wgk8ws8ca2bz2kr5nkqefrngtizuum901cv7hmhgqnsjuc1-392uyq8gmjgp9dj484y8id8jq \ 172.28.231.215:2377 # 将其开的节点设置为 manger 节点 # This node joined a swarm as a manager.
docker node ls # 显示由三个 manager 节点 # ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS # 9xujdtp2c7dob2t1o704tgwvl iZuf6brcie4578p0e13tg8Z Down Active # abele1bkn04awsnvvfzj0dof2 iZuf6brcie4578p0e13tg9Z Ready Active Reachable # o97d3m17864yftbmq6kdaxel4 * iZuf6brcie4578p0e13tg8Z Ready Active Reachable # qr1s9a3q7h3j8dw48juw1emg4 myvm01 Ready Active Leader # y1gs7gsyuwoefjvmw8d9eswrm iZuf6brcie4578p0e13tgaZ Ready Active
system stop docker # 重复之前的实验,停止一个 manager 节点
docker node ls # 到备用 manager 节点,测试节点信息,可用 # ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS # 9xujdtp2c7dob2t1o704tgwvl iZuf6brcie4578p0e13tg8Z Down Active # abele1bkn04awsnvvfzj0dof2 iZuf6brcie4578p0e13tg9Z Down Active Unreachable # o97d3m17864yftbmq6kdaxel4 iZuf6brcie4578p0e13tg8Z Ready Active Reachable # qr1s9a3q7h3j8dw48juw1emg4 * myvm01 Ready Active Leader # y1gs7gsyuwoefjvmw8d9eswrm iZuf6brcie4578p0e13tgaZ Ready Active
搭建集群
docker-compose up 项目,单机
swarm 集群 services 高可用
容器 -> 服务 -> 副本
docker run 容器启动,不能扩容
docker service 服务,可扩容
1 2 3 4 5 6 7 8 9 10 11 12 13 14
docker service # Usage: docker service COMMAND # Manage services # Options: # --help Print usage # Commands: # create Create a new service # inspect Display detailed information on one or more services # ls List services # ps List the tasks of a service # rm Remove one or more services # scale Scale one or multiple replicated services # update Update a service # Run 'docker service COMMAND --help' for more information on a command.
docker service create -p 8888:80 --name my-nginx nginx # 创建服务
docker service ps my-nginx # ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS # yb78d9o2lsyp my-nginx.1 nginx:latest myvm01 Running Running about a minute ago
docker service ls # ID NAME MODE REPLICAS IMAGE # sgcat9l69srz my-nginx replicated 1/1 nginx:latest
docker ps # 这个服务是随机创建在 manager 节点上的
docker service update --replicas 3 my-nginx # 添加三个副本
docker ps # 去各个节点上看可以看到如下信息,names 为 1-3 # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 902bbdf9eb3a nginx@sha256:75a55d33ecc73c2a242450a9f1cc858499d468f077ea942867e662c247b5e412 "/docker-entrypoin..." 9 minutes ago Up 9 minutes 80/tcp my-nginx.1.yb78d9o2lsyp0wg7558vn0eew
Q: 在最后的 spring 项目实战的 dockerfile 中我明明写了 EXPOSE 8080 为什么我在 run 的时候还要加 p 参数? A: 查看了一下文档,发现这个 EXPOSE 只是起说明作用, run 的时候并不会自动暴露,但是他有一个好处,就是你写了之后,如果用 P 随机的模式的话,他会自动暴露