Docker 学习记录

部署nginx

# 搜索nginx
➜  ~ docker search nginx
NAME                                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                                             Official build of Nginx.                        18362     [OK]
bitnami/nginx                                     Bitnami nginx Docker Image                      157                  [OK]
bitnami/nginx-ingress-controller                  Bitnami Docker Image for NGINX Ingress Contr…   25                   [OK]
ubuntu/nginx                                      Nginx, a high-performance reverse proxy & we…   84
kasmweb/nginx                                     An Nginx image based off nginx:alpine and in…   4
rancher/nginx-ingress-controller                                                                  11
rancher/nginx-ingress-controller-defaultbackend                                                   2
bitnami/nginx-exporter                                                                            3
rancher/nginx                                                                                     2
rapidfort/nginx-ib                                RapidFort optimized, hardened image for NGIN…   0
rapidfort/nginx                                   RapidFort optimized, hardened image for NGINX   3
vmware/nginx-photon                                                                               1
bitnami/nginx-ldap-auth-daemon                                                                    3
rapidfort/nginx-official                          RapidFort optimized, hardened image for NGIN…   1
vmware/nginx                                                                                      2
rancher/nginx-conf                                                                                0
linuxserver/nginx                                 An Nginx container, brought to you by LinuxS…   189
privatebin/nginx-fpm-alpine                       PrivateBin running on an Nginx, php-fpm & Al…   72                   [OK]
bitnami/nginx-intel                                                                               1
rancher/nginx-ssl                                                                                 0
circleci/nginx                                    This image is for internal use                  2
continuumio/nginx-ingress-ws                                                                      0
rancher/nginx-ingress-controller-amd64                                                            0
webdevops/nginx                                   Nginx container                                 11                   [OK]
bitnamicharts/nginx                                                                               0

#下载nginx
➜  ~ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
f1f26f570256: Pull complete
7f7f30930c6b: Pull complete
2836b727df80: Pull complete
e1eeb0f1c06b: Pull complete
86b2457cc2b0: Pull complete
9862f2ee2e8c: Pull complete
Digest: sha256:2ab30d6ac53580a6db8b657abf0f68d75360ff5cc1670a85acb5bd85ba1b19c0
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

#运行nginx
➜  ~ docker run -d --name nginx01 -p 8080:80 nginx
9f7f243d4d751f008f8ce6811f4ba26aa06b768478f9f3355d4c7a79b1b8e4de
➜  ~ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
9f7f243d4d75   nginx     "/docker-entrypoint.…"   5 seconds ago   Up 4 seconds   0.0.0.0:8080->80/tcp, :::8080->80/tcp   nginx01

#运行本机自检测试
➜  ~ curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<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>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

#进入容器
➜  ~ docker exec -it 9f7f243d4d75 /bin/bash
root@9f7f243d4d75:/# ls
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@9f7f243d4d75:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@9f7f243d4d75:/# cat /etc/nginx/
cat: /etc/nginx/: Is a directory
root@9f7f243d4d75:/# cat /etc/nginx/
conf.d/         fastcgi_params  mime.types      modules/        nginx.conf      scgi_params     uwsgi_params
root@9f7f243d4d75:/# cat /etc/nginx/nginx.conf

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
root@9f7f243d4d75:/#

部署tomcat

#下载
➜  ~ docker pull tomcat:9.0
9.0: Pulling from library/tomcat
74ac377868f8: Pull complete
a182a611d05b: Pull complete
ad4fe29a3001: Pull complete
9d52462c5181: Pull complete
ac04a5bb8dd2: Pull complete
bcf698d11bcf: Pull complete
3c8f99a77788: Pull complete
Digest: sha256:b365c17063141d128fba80f59ab32f6674a00d6fd77c819543e2580e645edc2a
Status: Downloaded newer image for tomcat:9.0
docker.io/library/tomcat:9.0

#运行
➜  ~ docker run -d -p 8888:8080 --name tomcat01 tomcat:9.0
ef6618cc447522d8db12c571d13f24b769f7195b9ac3582b448af0574f074019

#访问正常,但是网页出现404
➜  ~ curl localhost:8888
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/9.0.73</h3></body></html>#      

# 问题: 没有apps,缺少很多linux命令
root@ef6618cc4475:/usr/local/tomcat/webapps# pwd
/usr/local/tomcat/webapps
root@ef6618cc4475:/usr/local/tomcat/webapps# ls

#进入容器拷贝原来的网站
cp -r webapps.dist/* webapps/

#测试成功
➜  ~ curl localhost:8888
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Apache Tomcat/9.0.73</title>
        <link href="favicon.ico" rel="icon" type="image/x-icon" />
        <link href="tomcat.css" rel="stylesheet" type="text/css" />
    </head>

    <body>
        <div id="wrapper">
            <div id="navigation" class="curved container">
                <span id="nav-home"><a href="https://tomcat.apache.org/">Home</a></span>
                <span id="nav-hosts"><a href="/docs/">Documentation</a></span>
                <span id="nav-config"><a href="/docs/config/">Configuration</a></span>
                <span id="nav-examples"><a href="/examples/">Examples</a></span>
                <span id="nav-wiki"><a href="https://cwiki.apache.org/confluence/display/TOMCAT/">Wiki</a></span>
                <span id="nav-lists"><a href="https://tomcat.apache.org/lists.html">Mailing Lists</a></span>
                <span id="nav-help"><a href="https://tomcat.apache.org/findhelp.html">Find Help</a></span>
                <br class="separator" />
            </div>
            <div id="asf-box">
                <h1>Apache Tomcat/9.0.73</h1>
            </div>
            <div id="upper" class="curved container">
                <div id="congrats" class="curved container">
                    <h2>If you're seeing this, you've successfully installed Tomcat. Congratulations!</h2>
                </div>

...............

部署ES+kibana

# es 暴露的端口非常多
# es 十分耗内存
# es 的数据需要挂载到安全目录
# 官方启动es
$ docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# docker stats 查看运行状态
CONTAINER ID   NAME            CPU %     MEM USAGE / LIMIT     MEM %     NET I/O          BLOCK I/O         PIDS
fd89e080657f   elasticsearch   0.25%     1.275GiB / 3.701GiB   34.44%    1.1kB / 0B       1.08GB / 26.2MB   42
ef6618cc4475   tomcat01        0.15%     49.75MiB / 3.701GiB   1.31%     21.6kB / 169kB   464MB / 21MB      30
# 测试是否成功
➜  ~ curl localhost:9200
{
  "name" : "fd89e080657f",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "qBgJcn3zRyaN3H_tr14hIg",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date" : "2020-03-26T06:34:37.794943Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

#增加内存限制,-e 配置环境变量
docker run -d --name elasticsearch02 --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx1024m" elasticsearch:7.6.2
# docker stats 查看一下状态
CONTAINER ID   NAME            CPU %     MEM USAGE / LIMIT     MEM %     NET I/O          BLOCK I/O        PIDS
881e65f95ad0   elasticsearch   0.38%     363.6MiB / 3.701GiB   9.59%     656B / 0B        13.4MB / 1.6MB   42
ef6618cc4475   tomcat01        0.15%     57.83MiB / 3.701GiB   1.53%     21.6kB / 169kB   489MB / 21MB     30

可视化

  • portainer(临时使用)
docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
  • Rancher (CI/CD )

Docker 镜像讲解

镜像是什么

镜像是一种轻量级,可执行的独立软件包,用来打包软件运行的环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代理,运行时,库,环境变量和配置文件

所有的应用,直接打包docker镜像,就额可以直接跑起来!

如何得到镜像:

  • 从远程下载
  • 朋友拷贝给你
  • 自己制作一个镜像DockerFile

Docker镜像加载原理

UnionFS (联合文件系统)

UnionFS 是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite serveral directories into a single virtual filessystem)。 UnionFS文件系统是Docker镜像的基础,镜像可以通过分层来进行集成,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联通加载会吧各层文件系统叠加,这样最终的文件系统包含所有底层的文件目录

例如:git

image-20230411163526818

平时我们安装虚拟机的CentOs都是好几个G,为什么docker才几百M

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

虚拟机启动是分钟级别的,容器是秒级的

分层的理解

下载docker镜像时一层一层的其实就是分层最直观的体现(已经下载过得不会重复下载)

➜  ~ docker pull redis
Using default tag: latest
latest: Pulling from library/redis
f1f26f570256: Already exists
8a1809b0503d: Pull complete
d792b14d05f9: Pull complete
ad29eaf93bf6: Pull complete
7cda84ccdb33: Pull complete
95f837a5984d: Pull complete
Digest: sha256:7b83a0167532d4320a87246a815a134e19e31504d85e8e55f0bb5bb9edf70448
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
# 通过 docker image inspect redis查看层级

"RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:3af14c9a24c941c626553628cf1942dcd94d40729777f2fcfbcd3b8a3dfccdd6",
                "sha256:79f41069ccc18bcd9600999108724c0f2e6454fdcdee09fc594166c7184f0244",
                "sha256:2cf793f55eadaecdcc5c2fdf7d56c1cd3477c29b4a987f5c0005e5e19c234cc8",
                "sha256:d4e8b2ef264eedaa9f75ab229b7da2b311961e1fabd19d6ade682f9779f15d7e",
                "sha256:eb86ff5c5e2997063250da313143e7693468b8e35f7f239064eda104e6afbaa7",
                "sha256:4324b0b9966a5ac99b470ace4ff3b7a595cb8ed3e3969b7492933a06d85bbb55"
            ]
},
理解:

所有的docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像之上,创建新的镜像层。

分层的好处

最大的一个好处就是 - 共享资源

比如:有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

这时可能就有人会问了:如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是否也会被修改? 答案:不会!因为修改会被限制在单个容器内。

这就是我们接下来要学习的容器 Copy-on-Write 特性

容器的可写层

当容器启动时,一个新的可写层被加载到镜像的顶部。 这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。所有操作都是针对容器层的,只有容器层是可写的,容器层下面的所有镜像层都是只读的。

如何提交自己的镜像

commit 镜像

docker commit 提交容器成为一个新的副本

#命令和git原理类似
docker commit -m=“提交的描述信息” -a="作者" 容器id 目标镜像名:[Tag]

实战测试
# 启动一个默认的tomcat ,发现默认的tomcat是没有webapps,是由于镜像的原因

# 我自己拷贝进去了基础的文件,然后提交镜像,可以看出来拷贝过的文件体积大一点,因为有东西添加进去了
➜  ~ docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED         STATUS         PORTS                                       NAMES
23de9dacab5c   tomcat    "catalina.sh run"   8 minutes ago   Up 8 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   strange_robinson
➜  ~ docker commit -a="verfolgerle" -m="add webapps app" 23de9dacab5c tomcat-app:1.0
sha256:e331648b4a1ea3dd8adaca0b0f500f42cc53b0d0af8c6165fd17b9127044d4a5
➜  ~ docker images
REPOSITORY               TAG       IMAGE ID       CREATED         SIZE
tomcat-app               1.0       e331648b4a1e   9 seconds ago   479MB
nginx                    latest    080ed0ed8312   13 days ago     142MB
tomcat                   9.0       061a3c8c49ee   2 weeks ago     477MB
tomcat                   latest    608294908754   2 weeks ago     475MB
redis                    latest    31f08b90668e   2 weeks ago     117MB
portainer/portainer-ce   latest    a87d51c7a324   6 weeks ago     272MB
elasticsearch            7.6.2     f29a1ee41030   3 years ago     791MB

到了这里才算入门docker!

容器数据卷

什么是容器数据卷

docker容器之间的数据共享技术,容器中产生的数据可以同步到本地

如果数据在容器中,删除容器后,数据就会丢失,需求:数据可以持久化

Mysql, 容器删了等于删库跑路,需求: 数据可以存储在本地

容器之间可以有一个数据共享的技术!

使用数据卷

方式一:直接使用命令来挂载 -v

  • docker run -it -v 主机目录:容器内目录
# docker run -it -v /home/ceshi:/home centos /bin/bash 
# docker ps 
➜  ~ docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
596f2d693b67   centos    "/bin/bash"   5 minutes ago   Up 5 minutes             modest_zhukovsky
# docker inspect 596f2d693b67
"Mounts": [
            {
                "Type": "bind",
                "Source": "/home/ceshi",
                "Destination": "/home",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
]
测试数据是否双向绑定

1,在主机新建test.dir ,然后在容器查看是否同步创建

image-20230411174617861

2, 停止容器,并在主机新建一个文件,再次确认是否同步创建

image-20230411175037807

3, 启动容器,确认容器内是否同步

➜  ceshi docker start 596f2d693b67
596f2d693b67
➜  ceshi docker attach 596f2d693b67
[root@596f2d693b67 /]# ls
bin  etc   lib    lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@596f2d693b67 /]# cd /home/
[root@596f2d693b67 home]# ls
test-update  test.dir
[root@596f2d693b67 home]# cat test-update
hello docker, did you see here ?
[root@596f2d693b67 home]#

思考问题。如果每次改动nginx的配置文件,都要进入容器内部就会十分麻烦,我要是可以在容器外部提供一个映射路径,达到在容器修改文件,容器内部自动修改?

当然可以,通过上面的方式可以自动同步

Mysql 数据持久化

思考: 如何保证Mysql删除容器时保留数据

# 第一步还是搜索镜像
➜  ~ docker search mysql
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                           MySQL is a widely used, open-source relation…   14041     [OK]
mariadb                         MariaDB Server is a high performing open sou…   5356      [OK]
percona                         Percona Server is a fork of the MySQL relati…   603       [OK]
phpmyadmin                      phpMyAdmin - A web interface for MySQL and M…   781       [OK]
circleci/mysql                  MySQL is a widely used, open-source relation…   29
bitnami/mysql                   Bitnami MySQL Docker Image                      83                   [OK]
bitnami/mysqld-exporter                                                         4
ubuntu/mysql                    MySQL open source fast, stable, multi-thread…   45
cimg/mysql                                                                      0
rapidfort/mysql                 RapidFort optimized, hardened image for MySQL   14
google/mysql                    MySQL server for Google Compute Engine          23                   [OK]
rapidfort/mysql8-ib             RapidFort optimized, hardened image for MySQ…   0
hashicorp/mysql-portworx-demo                                                   0
rapidfort/mysql-official        RapidFort optimized, hardened image for MySQ…   0
newrelic/mysql-plugin           New Relic Plugin for monitoring MySQL databa…   1                    [OK]
databack/mysql-backup           Back up mysql databases to... anywhere!         82
linuxserver/mysql               A Mysql container, brought to you by LinuxSe…   38
bitnamicharts/mysql                                                             0
mirantis/mysql                                                                  0
docksal/mysql                   MySQL service images for Docksal - https://d…   0
vitess/mysqlctld                vitess/mysqlctld                                1                    [OK]
linuxserver/mysql-workbench                                                     48
eclipse/mysql                   Mysql 5.7, curl, rsync                          0                    [OK]
drud/mysql                                                                      0
ilios/mysql                     Mysql configured for running Ilios              1                    [OK]

# 获取镜像
➜  ~ docker pull mysql:5.7
5.7: Pulling from library/mysql
e83e8f2e82cc: Pull complete
0f23deb01b84: Pull complete
f5bda3b184ea: Pull complete
ed17edbc6604: Pull complete
33a94a6acfa7: Pull complete
3686cf92b89d: Pull complete
f81535a6a8bf: Pull complete
4bffb03ea5e2: Pull complete
49348ef8dcaa: Pull complete
509d665d0cf5: Pull complete
adc919b937fd: Pull complete
Digest: sha256:bf18020f32cc5d8f5e2add516d52fbf3afc3de431457076340e938596c528171
Status: Downloaded newer image for mysql:5.7

# 运行镜像时需要做数据挂载 !安装配置mysql的时候是需要配置密码的
# 官方测试
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag 
# 启动自己的
-p 端口映射
-v 数据卷挂载
-d 后台运行
-e 环境变量
--name 设置名称 
$ docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=Evi19h0st --name mysql01 mysql:5.7

#启动成功后,用sqlyog 连接测试

mysql连接测试

image-20230416165943785

# 在本地创建一个test 数据库,然后查看容器是否同步创建 !

image-20230416170523537

# 发现已经同步创建
ls /home/mysql/data | grep test
test

# 删除容器确认数据是否持久化
docker rm -f mysql01
mysql01
# 发现数据没有丢失,这就实现了容器数据持久化问题!
➜  ~ ls /home/mysql/data
auto.cnf    ca.pem           client-key.pem  ibdata1      ib_logfile1  mysql       performance_schema  public_key.pem   server-key.pem  test
ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile0  ibtmp1       mysql.sock  private_key.pem     server-cert.pem  sys

具名挂载和匿名挂载

# 匿名挂载
-v 容器内路径 
# 启动镜像
➜  ~ docker run -d -P -v /etc/nginx --name nginx01 nginx
# 查看所有volume的情况
➜  ~ docker volume ls
DRIVER    VOLUME NAME
local     386f4cc72ebf7eadafc62cbc078082e820a1da428c37080bc200f42b56d77e39
local     portainer_data
# 这里发现这种就是匿名挂载卷,是没有指定名字的挂载
local     386f4cc72ebf7eadafc62cbc078082e820a1da428c37080bc200f42b56d77e39

# 具名挂载
-v 卷名:容器内的路径 #注意不要添加"/", 否则变成绝对路径
➜  ~ docker run -d -P -v juming:/etc/nginx --name nginx02 nginx
fdaf507e06366b2977653547de4a1931e4560d9a3d524af6cbd5f74f8c7b9b30

# 查看所有volume的情况
➜  ~ docker volume ls
DRIVER    VOLUME NAME
local     386f4cc72ebf7eadafc62cbc078082e820a1da428c37080bc200f42b56d77e39
local     juming
local     portainer_data

# 这里发现已经被具名挂载了
local     juming

# 查看volume 具体位置
➜  ~ docker volume inspect juming
[
    {
        "CreatedAt": "2023-04-16T05:50:30-04:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming/_data",
        "Name": "juming",
        "Options": null,
        "Scope": "local"
    }
]

所有docker卷,如果没有使用“/”指定具体目录的情况下,所有的卷默认挂载的路径在

# /var/lib/docker/volumes/xxxx/_data

➜  ~ ls /var/lib/docker/volumes/
386f4cc72ebf7eadafc62cbc078082e820a1da428c37080bc200f42b56d77e39  backingFsBlockDev  juming  metadata.db  portainer_data
➜  ~ docker volume ls
DRIVER    VOLUME NAME
local     386f4cc72ebf7eadafc62cbc078082e820a1da428c37080bc200f42b56d77e39
local     juming
local     portainer_data

#同时也看到nginx的配置文件夹也映射出来
➜  ~ ls /var/lib/docker/volumes/juming/_data
conf.d  fastcgi_params  mime.types  modules  nginx.conf  scgi_params  uwsgi_params

我们大多时候推荐使用“具名挂载”, 不建议使用匿名挂载

# 如何确定挂载的类型
-v 容器内路径 #匿名
-v 卷名:容器内路径 #具名
-v /主机路径:容器内路径 #指定路径挂载

拓展: 权限

# 只读
docker run -d -P -v juming:/etc/nginx:ro --name nginx02 nginx
# 读写
docker run -d -P -v juming:/etc/nginx:rw --name nginx02 nginx

# ro 对容器权限做了限制,只能通过宿主机修改操作,容器内是无法修改操作的!

初识DockerFile

DockerFile 就是用来构建 docker 镜像的构建文件!

方式二

# 创建volume挂载测试文件夹并且新建dockerfile01写入脚本
# 容器指令都是需要大写的
mkdir docker-test-volume 
cd  docker-test-volume &&  echo '
FROM centos \
VOLUME ["volume01","volume02"] \
CMD echo "---end---" \
CMD /bin/bash \ ' > dockerfile01

# 创建自己的centos
➜  docker-test-volume docker build -f ./dockerfile1 -t verfolgerle/centos:1.0 .
[+] Building 1.6s (5/5) FINISHED
 => [internal] load .dockerignore                                                                                                                           1.1s
 => => transferring context: 2B                                                                                                                             0.0s
 => [internal] load build definition from dockerfile1                                                                                                       0.9s
 => => transferring dockerfile: 177B                                                                                                                        0.1s
 => [internal] load metadata for docker.io/library/centos:latest                                                                                            0.0s
 => [1/1] FROM docker.io/library/centos                                                                                                                     0.3s
 => exporting to image                                                                                                                                      0.1s
 => => exporting layers                                                                                                                                     0.0s
 => => writing image sha256:3fe61907202c18b4acfa4c53909aabad8c304c21db4db321c59f9f8eb3b7951a                                                                0.0s
 => => naming to docker.io/verfolgerle/centos:1.0   

 # 查看镜像是否生成
 ➜  docker-test-volume docker images
verfolgerle/centos   1.0       3fe61907202c   19 months ago   231MB

# 运行镜像自己生成的镜像并查看目录
docker-test-volume docker run  -it 3fe61907202c /bin/bash
[root@a5f5beb97f99 /]# ls -al
total 0
drwxr-xr-x.   1 root root  38 Apr 16 11:04 .
drwxr-xr-x.   1 root root  38 Apr 16 11:04 ..
-rwxr-xr-x.   1 root root   0 Apr 16 11:04 .dockerenv
lrwxrwxrwx.   1 root root   7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x.   5 root root 360 Apr 16 11:04 dev
drwxr-xr-x.   1 root root  66 Apr 16 11:04 etc
drwxr-xr-x.   2 root root   6 Nov  3  2020 home
lrwxrwxrwx.   1 root root   7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx.   1 root root   9 Nov  3  2020 lib64 -> usr/lib64
drwx------.   2 root root   6 Sep 15  2021 lost+found
drwxr-xr-x.   2 root root   6 Nov  3  2020 media
drwxr-xr-x.   2 root root   6 Nov  3  2020 mnt
drwxr-xr-x.   2 root root   6 Nov  3  2020 opt
dr-xr-xr-x. 132 root root   0 Apr 16 11:04 proc
dr-xr-x---.   2 root root 162 Sep 15  2021 root
drwxr-xr-x.  11 root root 163 Sep 15  2021 run
lrwxrwxrwx.   1 root root   8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 Nov  3  2020 srv
dr-xr-xr-x.  13 root root   0 Apr  8 02:43 sys
drwxrwxrwt.   7 root root 171 Sep 15  2021 tmp
drwxr-xr-x.  12 root root 144 Sep 15  2021 usr
drwxr-xr-x.  20 root root 262 Sep 15  2021 var
drwxr-xr-x.   2 root root   6 Apr 16 11:04 volume01
drwxr-xr-x.   2 root root   6 Apr 16 11:04 volume02

# 发现我们挂载的目录已经自动生成
drwxr-xr-x.   2 root root   6 Apr 16 11:04 volume01
drwxr-xr-x.   2 root root   6 Apr 16 11:04 volume02

# 在容器volume01 创建 test.txt 文件
[root@a5f5beb97f99 volume01]# touch test.txt

#新建一个终端。查看卷挂载的路径
➜  ~ docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED             STATUS             PORTS                                     NAMES
a5f5beb97f99   3fe61907202c   "/bin/bash"              4 minutes ago       Up 4 minutes                                                 kind_cartwright

➜  ~ docker inspect a5f5

...
"Mounts": [
            {
                "Type": "volume",
                "Name": "07e096f4d790f2834d1e166403be2f84a31a4cb6f988d58da75b3deaf68cda6e",
                "Source": "/var/lib/docker/volumes/07e096f4d790f2834d1e166403be2f84a31a4cb6f988d58da75b3deaf68cda6e/_data",
                "Destination": "volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "cfd46e4d36be69352e8a770fe188d62c02d9b17f5be76d47f0bd1ec68e688eaf",
                "Source": "/var/lib/docker/volumes/cfd46e4d36be69352e8a770fe188d62c02d9b17f5be76d47f0bd1ec68e688eaf/_data",
                "Destination": "volume02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
        "Config": {
# 测试刚刚新建的文件是否同步出来
➜  ~ ls  /var/lib/docker/volumes/07e096f4d790f2834d1e166403be2f84a31a4cb6f988d58da75b3deaf68cda6e/_data/
test.txt

这种方式我们未来使用的十分多,因为我们通常会自己构建镜像

数据卷容器

例如:多个Mysql 数据同步

image-20230416191745783

# 启动3个容器
# 创建docker01
➜  ~ docker run -it --name docker01 3fe61907202c 
[root@6a1308714b5f /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume01  volume02
# 创建docker02并继承docker01
➜  ~ docker run -it --name docker02 --volumes-from docker01 3fe61907202c
[root@c6b80bde1710 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume01  volume02

# 在docker01 下面的 volume01 创建 docker01-txt 文件
[root@6a1308714b5f /]# cd volume01
[root@6a1308714b5f volume01]# touch docker01-txt
[root@6a1308714b5f volume01]# ls
docker01-txt

# 查看docker02 下 volume01 是否同步创建成功
[root@c6b80bde1710 /]# cd volume01
[root@c6b80bde1710 volume01]# ls
docker01-txt
# 文件同步创建了,docker01 就是数据容器卷

# 创建docker03并继承docker01,并查看volume01的数据
➜  ~ docker run -it --name docker03 --volumes-from docker01 3fe61907202c
[root@cb2d426e41d1 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume01  volume02
[root@cb2d426e41d1 /]# cd volume01 && ls
docker01-txt

#在docker01的volume01下创建docker03-txt,并查看docker01和docker02的volume01下面是否同步创建
[root@cb2d426e41d1 /]# cd volume01 && touch docker03-txt && ls
docker01-txt  docker03-txt

# docker01 数据同步正常
[root@6a1308714b5f volume01]# ls
docker01-txt  docker03-txt
# docker02 数据同步正常
[root@c6b80bde1710 volume01]# ls
docker01-txt  docker03-txt

结论:只要通过--volumes-from就可以实现容器间的数据共享

# 测试,既然docker02和docker03都是继承docker01的数据,那么我们直接把docker01删除,确认数据是否依然存在
# 实验
➜  ~ docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                     PORTS     NAMES
cb2d426e41d1   3fe61907202c   "/bin/sh -c /bin/bash"   8 minutes ago    Up 8 minutes                         docker03
c6b80bde1710   3fe61907202c   "/bin/sh -c /bin/bash"   15 minutes ago   Up 15 minutes                        docker02
6a1308714b5f   3fe61907202c   "/bin/bash"              19 minutes ago   Exited (0) 8 seconds ago             docker01
➜  ~ docker rm -f 6a1308714b5f
6a1308714b5f
➜  ~ docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
cb2d426e41d1   3fe61907202c   "/bin/sh -c /bin/bash"   8 minutes ago    Up 8 minutes              docker03
c6b80bde1710   3fe61907202c   "/bin/sh -c /bin/bash"   15 minutes ago   Up 15 minutes             docker02

#查看docker03的volume01数据,发现数据并没有因docker01删除而删除
[root@cb2d426e41d1 volume01]# ls
docker01-txt  docker03-txt

# 查看docker02的volume01数据,发现数据并没有因docker01删除而删除
[root@c6b80bde1710 volume01]# ls
docker01-txt  docker03-txt

再次实验。创建docker04,并使用docker03为容器数据卷后,删除剩余的docker02,docker03,查看数据是否依然存在

# 创建docker04
➜  ~ docker run -it --name docker04 --volumes-from docker03 3fe61907202c
[root@3dfb059b75af /]#
[root@3dfb059b75af /]# cd volume01 && ls
docker01-txt  docker03-txt

# 发现数据已经继承了,现在删除docker02和docker03,并查看docker04数据是否存在
➜  ~ docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                      PORTS     NAMES
3dfb059b75af   3fe61907202c   "/bin/sh -c /bin/bash"   2 minutes ago    Up 2 minutes                          docker04
cb2d426e41d1   3fe61907202c   "/bin/sh -c /bin/bash"   15 minutes ago   Exited (0) 20 seconds ago             docker03
c6b80bde1710   3fe61907202c   "/bin/sh -c /bin/bash"   22 minutes ago   Exited (0) 23 seconds ago             docker02
➜  ~ docker rm cb2d426e41d1 c6b80bde1710
cb2d426e41d1
c6b80bde1710
➜  ~ docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
3dfb059b75af   3fe61907202c   "/bin/sh -c /bin/bash"   2 minutes ago   Up 2 minutes             docker04

# 除docker04外,其余容器都被删除,现在确认docker04下volume的数据是否被删除
[root@3dfb059b75af volume01]# ls
docker01-txt  docker03-txt
# 发现docker04数据并没有因为继承的容器删除而数据丢失 !

img

结论:由此发现,容器间的数据是以”拷贝状态“存在的。只要存在任一容器,数据都不会丢失

但你一旦把数据持久化到本地,即便容器都被删除,数据也不会丢失

思考,创建两个Mysql,并实现数据同步

#创建第一个mysql
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=Evi19h0st --name mysql01 mysql:5.7
#创建第二个mysql并同步继承第一个
docker run -d -p 3306:3306  -e MYSQL_ROOT_PASSWORD=Evi19h0st --name mysql02 --volumes-from mysql01 mysql:5.7

DockerFile

DockerFile 介绍

用来构建docker镜像的文件,命令参数脚本!

构建步骤

1、编写dockerfile文件

2、docker build 构建成为一个镜像

3、docker run 运行镜像

4、 docker push 发布镜像(DockerHub、阿里云镜像仓库)

查看一下官方是怎么做的

image-20230417145020789

# 参考资料
https://github.com/CentOS/sig-cloud-instance-images/blob/b2d195220e1c5b181427c3172829c23ab9cd27eb/docker/Dockerfile

FROM scratch
ADD centos-7-x86_64-docker.tar.xz /

LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20201113" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-11-13 00:00:00+00:00"

CMD ["/bin/bash"]

很多官方镜像都只有基础包,很多功能都没有,需要我们自行安装,所以我们通常都是自行构建镜像

DockerFile 构建过程

基础知识:

  1. 每个保留关键字(指令)都必须是大写字母
  2. 执行从上到下顺序执行
  3. # 表示注释
  4. 每一个指令都会创建提交一个新的镜像层,并提交!

image-20230417171401615

Dockerimages: 通过DockerFile 构建生成的镜像,最终发布和运行的产品

Docker 容器: 容器就是镜像运行起来提供的服务

DockerFile 的指令

FROM        # 基础镜像,一切从这里开始构建
MAINTAINER  # 镜像的作者
RUN         # 镜像构建的时候需要运行的命令
ADD         # 步骤,比如添加tomcat镜像
WORKDIR     # 镜像的工作目录
VOLUME      # 挂载的目录
EXPOSE      # 暴露的端口
CMD         # 指定这个容器启动的时候运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT  # 指定这个容器启动的时候运行的命令,可追加命令
ONBULID     # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY        # 类似ADD,将我们的文件拷贝到镜像中
ENV         # 构建的时候设置环境变量
COPY和ADD命令都可以将本地文件复制到Docker镜像中,但它们有一些区别:

1. COPY命令只能复制本地文件,而ADD命令除了可以复制本地文件,还可以复制远程文件,例如ADD http://example.com/file.tar.gz /tmp/。

2. ADD命令支持自动解压缩压缩文件,例如ADD file.tar.gz /tmp/会自动解压缩file.tar.gz文件,而COPY命令不支持自动解压缩。

3. COPY命令的语法比ADD命令简单,只需要指定源文件和目标路径即可,例如COPY app.py /app/。而ADD命令的语法比较复杂,可以指定源文件、目标路径、解压缩选项等,例如ADD file.tar.gz /tmp/ --extract=TRUE。

因此,一般情况下建议使用COPY命令来复制本地文件到Docker镜像中,除非需要复制远程文件或自动解压缩压缩文件等特殊需求。

实战测试

Docker Hub 中 99% 镜像都是从这个基础镜像过来的FROM scratch,然后配置需要的软件和配置来进行构建

https://github.com/CentOS/sig-cloud-instance-images/blob/b2d195220e1c5b181427c3172829c23ab9cd27eb/docker/Dockerfile

FROM scratch
ADD centos-7-x86_64-docker.tar.xz /

LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20201113" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-11-13 00:00:00+00:00"

CMD ["/bin/bash"]

创建一个自己的Centos

# 我们可以发现,我们很多功能是没有的
➜  dockerfile docker run -it centos
[root@4a60e554e0f3 /]# vim
bash: vim: command not found
[root@4a60e554e0f3 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@4a60e554e0f3 /]# ifconfig
bash: ifconfig: command not found
[root@4a60e554e0f3 /]#

# 编写自己的dockerfile文件
➜  dockerfile cat mydockerfile-centos
FROM centos
MAINTAINER verfolgerle<test@123.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN cd /etc/yum.repos.d/
RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
RUN yum install vim -y
RUN yum install net-tools -y

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash

#通过文件构建镜像
➜  dockerfile docker build -f ./mydockerfile-centos -t mycentos:0.1 .
[+] Building 27.9s (11/11) FINISHED
 => [internal] load build definition from mydockerfile-centos                                                                                 0.0s
 => => transferring dockerfile: 516B                                                                                                          0.0s
 => [internal] load .dockerignore                                                                                                             0.0s
 => => transferring context: 2B                                                                                                               0.0s
 => [internal] load metadata for docker.io/library/centos:latest                                                                              0.0s
 => [1/7] FROM docker.io/library/centos                                                                                                       0.0s
 => CACHED [2/7] WORKDIR /usr/local                                                                                                           0.0s
 => [3/7] RUN cd /etc/yum.repos.d/                                                                                                            0.2s
 => [4/7] RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*                                                                   0.2s
 => [5/7] RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*                        0.2s
 => [6/7] RUN yum -y install vim                                                                                                             23.4s
 => [7/7] RUN yum -y install net-tools                                                                                                        3.3s
 => exporting to image                                                                                                                        0.5s
 => => exporting layers                                                                                                                       0.5s
 => => writing image sha256:5c9b15a74851034b8449b9e8ed3d12783ca30c1e86b90b3b88c3930caaf8bc0e                                                  0.0s
 => => naming to docker.io/library/mycentos:0.1  

 # 测试运行
➜  ~ docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
mycentos             0.1       5c9b15a74851   17 hours ago    312MB
nginx                latest    6efc10a0510f   5 days ago      142MB
mysql                5.7       3f3447deacaa   2 weeks ago     455MB
verfolgerle/centos   1.0       3fe61907202c   19 months ago   231MB
centos               latest    5d0da3dc9764   19 months ago   231MB
➜  ~ docker run -it 5c9b15a74851
[root@57c236506945 local]# pwd
/usr/local
[root@57c236506945 local]#
[root@57c236506945 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 8  bytes 656 (656.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

# 我们可以列出本地镜像变更的历史
➜  ~ docker history 5c9b15a74851
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
5c9b15a74851   17 hours ago    CMD ["/bin/sh" "-c" "/bin/bash"]                0B        buildkit.dockerfile.v0
<missing>      17 hours ago    CMD ["/bin/sh" "-c" "echo \"---end---\""]       0B        buildkit.dockerfile.v0
<missing>      17 hours ago    CMD ["/bin/sh" "-c" "echo $MYPATH"]             0B        buildkit.dockerfile.v0
<missing>      17 hours ago    EXPOSE map[80/tcp:{}]                           0B        buildkit.dockerfile.v0
<missing>      17 hours ago    RUN /bin/sh -c yum -y install net-tools # bu…   14.7MB    buildkit.dockerfile.v0
<missing>      17 hours ago    RUN /bin/sh -c yum -y install vim # buildkit    66.3MB    buildkit.dockerfile.v0
<missing>      17 hours ago    RUN /bin/sh -c sed -i 's|#baseurl=http://mir…   8.8kB     buildkit.dockerfile.v0
<missing>      17 hours ago    RUN /bin/sh -c sed -i 's/mirrorlist/#mirrorl…   8.82kB    buildkit.dockerfile.v0
<missing>      17 hours ago    RUN /bin/sh -c cd /etc/yum.repos.d/ # buildk…   0B        buildkit.dockerfile.v0
<missing>      17 hours ago    WORKDIR /usr/local                              0B        buildkit.dockerfile.v0
<missing>      17 hours ago    ENV MYPATH=/usr/local                           0B        buildkit.dockerfile.v0
<missing>      17 hours ago    MAINTAINER verfolgerle<test@123.com>            0B        buildkit.dockerfile.v0
<missing>      19 months ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      19 months ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
<missing>      19 months ago   /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0…   231MB

# 可以通过 docker history 的方式查看别人的镜像是如何制作的
# 例如我们查看一下nginx官方是如何制作的
➜  ~ docker history 6efc10a0510f
IMAGE          CREATED      CREATED BY                                      SIZE      COMMENT
6efc10a0510f   5 days ago   /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B
<missing>      5 days ago   /bin/sh -c #(nop)  STOPSIGNAL SIGQUIT           0B
<missing>      5 days ago   /bin/sh -c #(nop)  EXPOSE 80                    0B
<missing>      5 days ago   /bin/sh -c #(nop)  ENTRYPOINT ["/docker-entr…   0B
<missing>      5 days ago   /bin/sh -c #(nop) COPY file:e57eef017a414ca7…   4.62kB
<missing>      5 days ago   /bin/sh -c #(nop) COPY file:abbcbf84dc17ee44…   1.27kB
<missing>      5 days ago   /bin/sh -c #(nop) COPY file:5c18272734349488…   2.12kB
<missing>      5 days ago   /bin/sh -c #(nop) COPY file:7b307b62e82255f0…   1.62kB
<missing>      5 days ago   /bin/sh -c set -x     && addgroup --system -…   61.6MB
<missing>      5 days ago   /bin/sh -c #(nop)  ENV PKG_RELEASE=1~bullseye   0B
<missing>      5 days ago   /bin/sh -c #(nop)  ENV NJS_VERSION=0.7.11       0B
<missing>      5 days ago   /bin/sh -c #(nop)  ENV NGINX_VERSION=1.23.4     0B
<missing>      5 days ago   /bin/sh -c #(nop)  LABEL maintainer=NGINX Do…   0B
<missing>      6 days ago   /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>      6 days ago   /bin/sh -c #(nop) ADD file:11b1acca3f68b5c57…   80.5MB

CMD 和 ENTRYPOINT 的区别

  • CMD
# 创建CMD测试文件,并build运行
➜  dockerfile cat dockerfile-cmd
FROM centos
CMD {"ls","-a"}
➜  dockerfile docker build -f dockerfile-cmd -t cmdtest ,
➜  ~ docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
cmdtest              latest    df636de4ed00   19 months ago   231MB
➜  dockerfile docker run -it df636de4ed00
.  ..  .dockerenv  bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
# 运行后发现`ls -a` 命令生效
# 现在要追加一个命令,变成`ls -al`
# 发现报错,这是因为在CMD 命令下,`-l` 替换了原来的 `ls -a` ,而 `-l` 不是命令,所以报错
➜  dockerfile docker run df636de4ed00 -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
# 所以我们需要这样操作
➜  dockerfile docker run df636de4ed00 ls -al
total 0
drwxr-xr-x.   1 root root   6 Apr 18 02:58 .
drwxr-xr-x.   1 root root   6 Apr 18 02:58 ..
-rwxr-xr-x.   1 root root   0 Apr 18 02:58 .dockerenv
lrwxrwxrwx.   1 root root   7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x.   5 root root 340 Apr 18 02:58 dev
drwxr-xr-x.   1 root root  66 Apr 18 02:58 etc
drwxr-xr-x.   2 root root   6 Nov  3  2020 home
lrwxrwxrwx.   1 root root   7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx.   1 root root   9 Nov  3  2020 lib64 -> usr/lib64
drwx------.   2 root root   6 Sep 15  2021 lost+found
drwxr-xr-x.   2 root root   6 Nov  3  2020 media
drwxr-xr-x.   2 root root   6 Nov  3  2020 mnt
drwxr-xr-x.   2 root root   6 Nov  3  2020 opt
dr-xr-xr-x. 121 root root   0 Apr 18 02:58 proc
dr-xr-x---.   2 root root 162 Sep 15  2021 root
drwxr-xr-x.  11 root root 163 Sep 15  2021 run
lrwxrwxrwx.   1 root root   8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 Nov  3  2020 srv
dr-xr-xr-x.  13 root root   0 Apr 16 15:34 sys
drwxrwxrwt.   7 root root 171 Sep 15  2021 tmp
drwxr-xr-x.  12 root root 144 Sep 15  2021 usr
drwxr-xr-x.  20 root root 262 Sep 15  2021 var
  • ENTRYPOINT
# 创建ENTRYPOINT测试文件
➜  dockerfile cat dockerfile-entrypoint
FROM centos
ENTRYPOINT {"ls","-a"}
# build 镜像
➜  dockerfile docker build -f dockerfile-entrypoint -t entrypointtest .
[+] Building 0.0s (5/5) FINISHED
 => [internal] load build definition from dockerfile-entrypoint                                                                               0.0s
 => => transferring dockerfile: 142B                                                                                                          0.0s
 => [internal] load .dockerignore                                                                                                             0.0s
 => => transferring context: 2B                                                                                                               0.0s
 => [internal] load metadata for docker.io/library/centos:latest                                                                              0.0s
 => CACHED [1/1] FROM docker.io/library/centos                                                                                                0.0s
 => exporting to image                                                                                                                        0.0s
 => => exporting layers                                                                                                                       0.0s
 => => writing image sha256:3c72b75f8d5b6bd317d7ab34a9b0643bf5354a5988c3da65e2720322db828e37                                                  0.0s
 => => naming to docker.io/library/entrypointtest                                                                                             0.0s

# 运行测试
➜  dockerfile docker run 3c72b75f8d5
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

# 命令追加测试,发现ENTRYPOINT不会报错,证明命令可追加
➜  dockerfile docker run 3c72b75f8d5 -l
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
➜  dockerfile

**DockerFile很多命令都有细微的区别,我们需要了解他们,最好的学习就是做实验做对比**

来自OpenAI的回答

假设我们有一个Python应用程序,它的入口文件是app.py,我们希望将这个应用程序打包成Docker镜像并运行。

使用CMD指令的Dockerfile如下:

​```
FROM python:3.8-slim-buster
WORKDIR /app
COPY app.py .
CMD ["python", "app.py"]
​```

使用ENTRYPOINT和CMD指令的Dockerfile如下:

​```
FROM python:3.8-slim-buster
WORKDIR /app
COPY app.py .
ENTRYPOINT ["python"]
CMD ["app.py"]
​```

这两个Dockerfile的区别在于CMD和ENTRYPOINT指令的使用方式不同。

在第一个Dockerfile中,我们使用了CMD指令来指定容器启动时要执行的命令,即运行Python解释器并执行app.py文件。这个命令可以被覆盖,例如我们可以使用docker run命令来覆盖CMD指令指定的命令,例如:

​```
docker run myapp python app.py
​```

这样就会覆盖CMD指令指定的命令,而运行Python解释器并执行app.py文件。

在第二个Dockerfile中,我们使用了ENTRYPOINT和CMD指令来指定容器启动时要执行的命令。ENTRYPOINT指令指定了Python解释器作为容器启动时要执行的命令,而CMD指令指定了app.py文件作为ENTRYPOINT指定命令的参数。这个命令不会被覆盖,例如我们使用docker run命令来覆盖CMD指令指定的参数,例如:

​```
docker run myapp /bin/bash
​```

这样就不会覆盖ENTRYPOINT指令指定的命令,而是执行/bin/bash命令,因为ENTRYPOINT指令指定的命令不会被覆盖。

总之,CMD指令可以被覆盖,而ENTRYPOINT指令不会被覆盖,这是它们的主要区别。

实战:构建tomcat镜像

  1. 准备好jdk和tomcat的压缩包

    jdk : https://builds.openlogic.com/downloadJDK/openlogic-openjdk/8u262-b10/openlogic-openjdk-8u262-b10-linux-x64.tar.gz

    tomcat : https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.73/bin/apache-tomcat-9.0.73.tar.gz

    ➜  build pwd
    /home/dockerfile/build
    ➜  build ls
    apache-tomcat-9.0.73.tar.gz  openlogic-openjdk-8u262-b10-linux-x64.tar.gz
  2. 编写DockerFile文件,官方命名是Dockerfile, build 会自动寻找这个名称,就可以不用-f 指定了!!!

    # Dockerfile 编写
    ➜ cat Dockerfile
    FROM centos
    MAINTAINER verfolgerel
    COPY readme.txt /usr/local/readme.txt 
    ADD openlogic-openjdk-8u262-b10-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-9.0.73.tar.gz  /usr/local/
    
    RUN cd /etc/yum.repos.d/
    RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
    RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
    RUN yum -y install vim
    
    ENV MYPATH /usr/local
    WORKDIR  $MYPATH
    
    ENV JAVA_HOME /usr/local/openlogic-openjdk-8u262-b10-linux-x64
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.73
    ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.73
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    
    EXPOSE 8080
    
    CMD /usr/local/apache-tomcat-9.0.73/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.73/logs/catalina.out 
  3. 构建自己的tomcat 镜像

    ➜  build docker build -t diy-tomcat .
    [+] Building 21.9s (14/14) FINISHED
    => [internal] load build definition from Dockerfile                                                                                          0.0s
    => => transferring dockerfile: 979B                                                                                                          0.0s
    => [internal] load .dockerignore                                                                                                             0.0s
    => => transferring context: 2B                                                                                                               0.0s
    => [internal] load metadata for docker.io/library/centos:latest                                                                              0.0s
    => [1/9] FROM docker.io/library/centos                                                                                                       0.0s
    => [internal] load build context                                                                                                             0.0s
    => => transferring context: 321B                                                                                                             0.0s
    => CACHED [2/9] COPY readme.txt /usr/local/readme.txt                                                                                        0.0s
    => CACHED [3/9] ADD openlogic-openjdk-8u262-b10-linux-x64.tar.gz /usr/local/                                                                 0.0s
    => CACHED [4/9] ADD apache-tomcat-9.0.73.tar.gz  /usr/local/                                                                                 0.0s
    => [5/9] RUN cd /etc/yum.repos.d/                                                                                                            0.2s
    => [6/9] RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*                                                                   0.2s
    => [7/9] RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*                        0.2s
    => [8/9] RUN yum -y install vim                                                                                                             19.9s
    => [9/9] WORKDIR  /usr/local                                                                                                                 0.0s
    => exporting to image                                                                                                                        1.3s
    => => exporting layers                                                                                                                       1.3s
    => => writing image sha256:c6b917869ef7f2fa2d3a0c5180fd76b93dc9a29792237078eb0eadde58d15dcf                                                  0.0s
    => => naming to docker.io/library/diy-tomcat    
  4. 运行diy-tomcat 镜像

    ➜  build docker run -d -p 9090:8080 --name diy-tomcat -v /home/tomcat/test:/usr/local/apache-tomcat-9.0.73/webapps/test -v /home/tomcat/logs/:/usr/local/apache-tomcat-9.0.73/logs c6b917869ef7f2
    e862926100ddb5d6c82b4ef034fb81efd64f2522211594ee35c6160e2c43c240
    
    # 文件挂载成功
    ➜  build cd /home/tomcat
    ➜  tomcat ls
    logs  test
    
    ➜  tomcat docker exec -it e862926100 /bin/bash
    [root@e862926100dd local]# ls
    apache-tomcat-9.0.73  etc    include  lib64    openlogic-openjdk-8u262-b10-linux-64  sbin   src
    bin                   games  lib      libexec  readme.txt                            share
    [root@e862926100dd local]# cd apache-tomcat-9.0.73/
    [root@e862926100dd apache-tomcat-9.0.73]# ls
    BUILDING.txt     LICENSE  README.md      RUNNING.txt  conf  logs  webapps
    CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin          lib   temp  work
    

发布自己的镜像

DockerHub

  1. 注册账号:https://hub.docker.com/

  2. 在服务器上提交自己的镜像

    $ docker login --help
    Usage:  docker login [OPTIONS] [SERVER]
    
    Log in to a registry.
    If no server is specified, the default is defined by the daemon.
    
    Options:
     -p, --password string   Password
         --password-stdin    Take the password from stdin
     -u, --username string   Username
    
    $ docker login -u verfolgerle
    Password:
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    
    Login Succeeded
    
    $ docker images
    REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
    diy-tomcat           latest    c6b917869ef7   8 days ago      519MB
    mycentos             0.1       5c9b15a74851   8 days ago      312MB
    nginx                latest    6efc10a0510f   13 days ago     142MB
    mysql                5.7       3f3447deacaa   3 weeks ago     455MB
    entrypointtest       latest    3c72b75f8d5b   19 months ago   231MB
    verfolgerle/centos   1.0       3fe61907202c   19 months ago   231MB
    centos               latest    5d0da3dc9764   19 months ago   231MB
    cmdtest              latest    df636de4ed00   19 months ago   231MB
    
    #把mycentos改一个名字,带上自己的用户名和版本号
    $ docker tag 5c9b15a74851 verfolgerle/lajicentos:0.0.1
    $ docker images
    REPOSITORY               TAG       IMAGE ID       CREATED         SIZE
    verfolgerle/lajicentos   0.0.1     5c9b15a74851   8 days ago      312MB
    
    # 上传镜像
    
    $ docker push verfolgerle/lajicentos:0.0.1
➜  ~ docker login -u verfolgerle
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

➜  ~ docker push leleleleleleltomcat
Using default tag: latest
The push refers to repository [docker.io/library/leleleleleleltomcat]
c82d7a0749a3: Preparing
2075a4b5d0c2: Preparing
77fdf1674876: Preparing
8d5d3ad8cbb6: Preparing
74ddd0ec08fa: Preparing
denied: requested access to the resource is denied  # 拒绝

#正确push方法:

# 增加一个tag
➜  ~ docker images
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
leleleleleleltomcat      latest    1845ce56f3ca   2 hours ago    687MB

➜  ~ docker tag 1845ce56f3ca verfolgerle/tomcat:1.0

➜  ~ docker images
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
leleleleleleltomcat      latest    1845ce56f3ca   2 hours ago    687MB
verfolgerle/tomcat       1.0       1845ce56f3ca   2 hours ago    687MB  # 多了一个一样的镜像

➜  ~ docker push verfolgerle/tomcat:1.0
The push refers to repository [docker.io/verfolgerle/tomcat]
c82d7a0749a3: Pushed
2075a4b5d0c2: Pushed
77fdf1674876: Pushed
8d5d3ad8cbb6: Pushed
74ddd0ec08fa: Pushed
1.0: digest: sha256:9b40f7fdf7f0c0f8de1d9167e99caa7f520dea989716dbd8eefec51a0fb7f52a size: 1373

Docker 网络

理解docker0

清空所有环境

# 删除所有docker
➜  ~ docker rm -f $(docker ps -aq)
e862926100dd
8c2da25ca309
01d05f8bfaf8
e8fdc02be83c
69882dc0c25e
d57c7ff7e28e
b13d92a1415a
2405ce0fee85
4241252f74b9
7be34b80c33a
175dd17e4800
57c236506945
4a60e554e0f3
3dfb059b75af
➜  ~ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
# 删除所有docker镜像
➜  ~ docker rmi -f $(docker images -a)
Untagged: mydiycentos:v1.1
Untagged: verfolgerle/mydiycentos:v1.1
Deleted: sha256:c0aa2b456a656906b835c78585470799f8b8f9dbfa5341dffc771f77afb95da2
Deleted: sha256:ef1a916f2678116b9e7e09c5e0c06e528ca39bc6cf2a205738aec6fa92ccfc81
Untagged: diy-tomcat:latest
Deleted: sha256:c6b917869ef7f2fa2d3a0c5180fd76b93dc9a29792237078eb0eadde58d15dcf
Untagged: mycentos:0.1
Deleted: sha256:5c9b15a74851034b8449b9e8ed3d12783ca30c1e86b90b3b88c3930caaf8bc0e
Untagged: nginx:latest
Untagged: nginx@sha256:63b44e8ddb83d5dd8020327c1f40436e37a6fffd3ef2498a6204df23be6e7e94
Deleted: sha256:6efc10a0510f143a90b69dc564a914574973223e88418d65c1f8809e08dc0a1f
Deleted: sha256:a489ce38666d5aff5d73930d115381b154a503b48c5534357d5183160f5b9bfa
Deleted: sha256:ce2a611250a8bb55b73959de5865489d566bf48e1342c74b46b107e9a224370e
Deleted: sha256:fa6c51798227fd451cc3ff628c46c1b62c0d1d08e43374be7000c78ad910c0c0
Deleted: sha256:c426467d564c8684df87356eb045dc50d8b5af9521e9775c1b6bb941135680de
Deleted: sha256:c6deada06ccd386201e5b95c38e19297cd3eeb5264d6413d9cc7441020816401
Deleted: sha256:ed7b0ef3bf5bbec74379c3ae3d5339e666a314223e863c70644f7522a7527461
Untagged: mysql:5.7
Untagged: mysql@sha256:bf18020f32cc5d8f5e2add516d52fbf3afc3de431457076340e938596c528171
Deleted: sha256:3f3447deacaa5bacab184fabbf821a785e13303b2e340465bdf7815b0284497b
Deleted: sha256:b51c74300d68b9b3950240d8603e4d36d317a9b142f321590cf63c3e0de54c8b
Deleted: sha256:4978400ffc88fb08ad9078f54b9c0b7bbdeb974eb47254bef400c3afcb1a5f64
Deleted: sha256:415ae5176ec060ee20567260329c59249ac0a14ace1231bd900b06160f1bf13a
Deleted: sha256:5ca10ce25add112849f8f21284987d8a979ec7da062bf19b4dec85eb2408223e
Deleted: sha256:56a19ae8978a0c01051769af8fdc0ddc3356f117b194e4c7db9d39d3e81a4b56
Deleted: sha256:0c03f32323e91eefa53c41b1fe030e2278dd7ce87cb854da695b03125e9db2cc
Deleted: sha256:38700ee823d5d82b695bb7d553973c0106384a6984b553e2af6d6fb9545d9636
Deleted: sha256:7cfca860605c4f16b1f255ebd51e2c801e00ac16997c7840428f88a2246cfebb
Deleted: sha256:0d8a62cb129e3cebaaef51f977b670282775d48a9cdaa021a0cb5ed73243a446
Deleted: sha256:66e6e199acb7395ac9a10b125841eafdfa3f80a1a3f710e0a0a9519da228bce2
Deleted: sha256:e74a57638021cebbbe0dda98a27675f9b53258050ee2c29c3e5fb7fb1f3ab533
Untagged: cmdtest:latest
Deleted: sha256:df636de4ed00d2fdcdccb51ead14b90bf0e0c187b58bb8ae8ec753b9a5469e44
Untagged: verfolgerle/centos:1.0
Deleted: sha256:3fe61907202c18b4acfa4c53909aabad8c304c21db4db321c59f9f8eb3b7951a
Untagged: entrypointtest:latest
Deleted: sha256:3c72b75f8d5b6bd317d7ab34a9b0643bf5354a5988c3da65e2720322db828e37
Untagged: centos:latest
Untagged: centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Deleted: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: mydiycentos:latest
Error response from daemon: No such image: v1.1:latest
Error response from daemon: No such image: 30:latest
Error response from daemon: No such image: hours:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: verfolgerle/mydiycentos:latest
Error response from daemon: No such image: v1.1:latest
Error response from daemon: No such image: c0aa2b456a65:latest
Error response from daemon: No such image: 30:latest
Error response from daemon: No such image: hours:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: latest:latest
Error response from daemon: No such image: c6b917869ef7:latest
Error response from daemon: No such image: 9:latest
Error response from daemon: No such image: days:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: mycentos:latest
Error response from daemon: No such image: 0.1:latest
Error response from daemon: No such image: 10:latest
Error response from daemon: No such image: days:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: latest:latest
Error response from daemon: No such image: 6efc10a0510f:latest
Error response from daemon: No such image: 2:latest
Error response from daemon: No such image: weeks:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: mysql:latest
Error response from daemon: No such image: 5.7:latest
Error response from daemon: No such image: 3:latest
Error response from daemon: No such image: weeks:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: latest:latest
Error response from daemon: No such image: df636de4ed00:latest
Error response from daemon: No such image: 19:latest
Error response from daemon: No such image: months:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: verfolgerle/centos:latest
Error response from daemon: No such image: 1.0:latest
Error response from daemon: No such image: 19:latest
Error response from daemon: No such image: months:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: latest:latest
Error response from daemon: No such image: 3c72b75f8d5b:latest
Error response from daemon: No such image: 19:latest
Error response from daemon: No such image: months:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
Error response from daemon: No such image: latest:latest
Error response from daemon: No such image: 5d0da3dc9764:latest
Error response from daemon: No such image: 19:latest
Error response from daemon: No such image: months:latest
Error response from daemon: No such image: ago:latest
Error response from daemon: invalid reference format: repository name must be lowercase
# ➜  ~ docker images -a
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

本机 ip 地址

   # ip a

   1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
      inet 127.0.0.1/8 scope host lo
         valid_lft forever preferred_lft forever
      inet6 ::1/128 scope host
         valid_lft forever preferred_lft forever
   2: eth0:  mtu 1500 qdisc mq state DOWN group default qlen 1000
      link/ether 00:15:5d:1c:17:0a brd ff:ff:ff:ff:ff:ff
   3: eth1:  mtu 1500 qdisc mq state UP group default qlen 1000
      link/ether 00:15:5d:1c:17:0b brd ff:ff:ff:ff:ff:ff
      inet 172.16.28.146/24 brd 172.16.28.255 scope global noprefixroute dynamic eth1
         valid_lft 69521sec preferred_lft 69521sec
      inet6 fe80::e0fe:e0b1:e9e0:1ec2/64 scope link noprefixroute
         valid_lft forever preferred_lft forever
   4: docker0:  mtu 1500 qdisc noqueue state DOWN group default
      link/ether 02:42:a6:db:8a:3e brd ff:ff:ff:ff:ff:ff
      inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
         valid_lft forever preferred_lft forever
      inet6 fe80::42:a6ff:fedb:8a3e/64 scope link
         valid_lft forever preferred_lft forever
  1. 本机回环地址
  2. 万兆内网地址
  3. 万兆外网地址
  4. docker 容器网络
#  docker run -d -P --name tomcat01 tomcat

# 查看容器内的网络地址
$ docker exec -it tomcat01 ip a
OCI runtime exec failed: exec failed: unable to start container process: exec: "ip": executable file not found in $PATH: unknown

# 安装iprouter2包
$ docker exec -it tomcat01 apt install iproute2
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  libatm1 libbpf0 libbsd0 libcap2-bin libelf1 libmd0 libmnl0 libpam-cap libxtables12
Suggested packages:
  iproute2-doc
The following NEW packages will be installed:
  iproute2 libatm1 libbpf0 libbsd0 libcap2-bin libelf1 libmd0 libmnl0 libpam-cap libxtables12
0 upgraded, 10 newly installed, 0 to remove and 7 not upgraded.
Need to get 1,430 kB of archives.
After this operation, 4,151 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://archive.ubuntu.com/ubuntu jammy/main amd64 libelf1 amd64 0.186-1build1 [51.0 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libbpf0 amd64 1:0.5.0-1ubuntu22.04.1 [140 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy/main amd64 libmd0 amd64 1.0.4-1build1 [23.0 kB]
Get:4 http://archive.ubuntu.com/ubuntu jammy/main amd64 libbsd0 amd64 0.11.5-1 [44.8 kB]
Get:5 http://archive.ubuntu.com/ubuntu jammy/main amd64 libmnl0 amd64 1.0.4-3build2 [13.2 kB]
Get:6 http://archive.ubuntu.com/ubuntu jammy/main amd64 libxtables12 amd64 1.8.7-1ubuntu5 [31.2 kB]

# 再次查看ip地址
# docker exec -it tomcat01 ip a
# 发现出现eth0@if7, 这是因为docker 自动分配
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# 思考,主机能不能ping通容器内部
是可以的
$ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.063 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.065 ms
^C
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.063/0.065/0.069/0.009 ms

原理

# 我们每分配一个docker,docker都会自动分配一个docker网络地址,主机的docker地址与容器的docker网络地址同一网段,即172.17.0.0/16,

桥接模式,veth-pair 技术!再次查看现在本机的网络

7: veth33ef845@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 5a:94:69:b3:a9:d9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::5894:69ff:feb3:a9d9/64 scope link
       valid_lft forever preferred_lft forever

*实验: 创建多一个tomcat02 并且再次查看主机和容器docker,发现多了一对网卡**

# 容器内IP地址
$ docker exec -it tomcat02 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
# 主机网络
9: veth554e521@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 9a:d4:e4:12:0c:54 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::98d4:e4ff:fe12:c54/64 scope link
       valid_lft forever preferred_lft forever
# 我们发现容器带来的网卡,都是一对对的
# veth-pair 就是一对虚拟设备接口,成对出现,相互连接
# 特性: 充当桥梁,连接各个虚拟网络设备
# openstack ,docker容器之间的连接,ovs的连接都是使用veth-pair 技术

思考,既然两个tomcat容器都是同一网段,那么他们是否可以ping通

# tomcat02 安装ping 工具
$ docker exec -it tomcat02 apt install iputils-ping
# ping 测试
➜  ~ docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.148 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.108 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.056 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.055 ms

docker0 就是充当路由器功能,只要删除容器,对应的网桥也会一并删除

image-20230516114209153

--link

思考一个场景,我们编写的微服务 datebase.url = ip, 项目不重启,数据库ip就换掉了,我们希望可以处理这个问题,直接ping 名字来访问容器?

# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

# 解决:通过link,我们可以创建一个tomcat03来测试
$ docker run -d -P --name tomcat03 --link tomcat02 tomcat
0a293bdc22b33a2f67d745bce5a8b65110d1b40c96a3c6cd9205e8c4972c107f

# 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.096 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.088 ms

#注意现在tomcat03 链接了tomcat02,但是反过来tomcat02 是没办法直接ping tomcat03的

docker 查看虚拟网卡

# docker network ls
NETWORK ID     NAME                 DRIVER    SCOPE
566cbd282a97   bridge               bridge    local
e093e1efed2a   host                 host      local
abec04ae3095   immich-app_default   bridge    local
e7eb5bc8ed59   none                 null      local
3439b65e721b   somenetwork          bridge    local

# 其实bridge 就是docker0, 也就是默认的网络,我们可以通过docker network inspect查看
# docker network inspect 566cbd282a97
[
    {
        "Name": "bridge",
        "Id": "566cbd282a9705ef18afd00eb3ed6f4fdaa1732e519e87abdf80fa4b9ed00c79",
        "Created": "2023-05-09T11:07:04.91532743-04: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": {
            "0a293bdc22b33a2f67d745bce5a8b65110d1b40c96a3c6cd9205e8c4972c107f": {
                "Name": "tomcat03",
                "EndpointID": "777fe8d167998686068e977a1de33c67bbd75f0b06d0eb6639e17c5d4f6107fe",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            },
            "700045d2a60a756dfcef96a9652df3ffb9c72a0cbf2743341b1fb5b5332ac303": {
                "Name": "tomcat01",
                "EndpointID": "b2f150b003e08c125c17b102556cd40504b96b71b5a60d76d4117c47cc0645ea",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "fad05e76b9fdec8630e357b132e02db1415a5c375bff64144c47df1db9e7a9dc": {
                "Name": "tomcat02",
                "EndpointID": "3d889f126c2de1ab908a0120539c3531ceb58bac2af5d9d1c88c0d9f1a5e783f",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/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": {}
    }
]

Link 本质:就是我们在host中配置了ip地址

image-20230516115229366

我们现在玩Docker已经不建议使用 --link 了

自定义网络,不使用docker0(不支持容器名访问)

在Docker中,--link是一种连接容器的方式,它可以将一个容器连接到另一个容器,并且在连接过程中会自动设置环境变量,使得连接的容器可以互相访问。

--link的用法如下:

​```
docker run --link <container_name>:<alias> <image_name>
​```

其中,<container_name>是要连接的容器的名称或ID,<alias>是连接的别名,<image_name>是要启动的镜像名称。

--link的优点:

1. 简单易用:使用--link可以很方便地连接容器,而不需要手动设置网络配置。

2. 自动设置环境变量:使用--link连接容器时,Docker会自动设置环境变量,使得连接的容器可以互相访问。

--link的缺点:

1. 不够灵活:使用--link连接容器时,需要手动指定要连接的容器名称或ID,这样就不够灵活,如果容器名称或ID发生变化,就需要重新设置。

2. 不支持多网络:使用--link连接容器时,只能连接到同一个网络中的容器,不支持连接到多个网络中的容器。

3. 不推荐使用:Docker官方已经不推荐使用--link连接容器,而是推荐使用Docker网络来连接容器,因为Docker网络更加灵活、可扩展和安全。

因此,虽然--link可以很方便地连接容器,但是它的缺点也比较明显,建议在实际应用中使用Docker网络来连接容器。

自定义网络

查看所有的网络

  ➜  ~ docker network ls
  NETWORK ID     NAME                 DRIVER    SCOPE
  566cbd282a97   bridge               bridge    local
  e093e1efed2a   host                 host      local
  abec04ae3095   immich-app_default   bridge    local
  e7eb5bc8ed59   none                 null      local
  3439b65e721b   somenetwork          bridge    local

网络模式

bridge : 桥接 (default)

none : 不配置网络

host :共享主机网络

container :容器网络连通!(用的少,局限先很大)

在Docker中,有以下几种网络模式:

  1. 桥接模式(Bridge Mode):这是默认的网络模式,它会为每个容器分配一个IP地址,并将它们连接到一个虚拟的桥接网络中。容器之间可以通过IP地址相互通信,也可以通过容器名称进行通信。

  2. 主机模式(Host Mode):在主机模式下,容器将与主机共享网络命名空间。这意味着容器将使用主机的IP地址,并且不需要进行端口映射。这种模式适用于需要最大化网络性能的场景。

  3. 容器模式(Container Mode):在容器模式下,容器将共享另一个容器的网络命名空间。这意味着它们将使用相同的IP地址和端口空间。这种模式适用于需要多个容器之间进行高速通信的场景。

  4. 网络模式(Network Mode):在网络模式下,容器将连接到指定的Docker网络中。这种模式适用于需要将容器连接到自定义网络的场景。

  5. 无网络模式(None Mode):在无网络模式下,容器将没有网络连接。这种模式适用于需要隔离容器的场景,例如安全测试。

测试

#我们直接启动的命令 --net bridge ,而这个就是我们的docker0
# 下面两个命令是一样的
docker run -d -P --name tomcat01 --net bridge tomcat
docker run -d -P --name tomcat01 tomcat 

# docker0特点, 默认,域名无法访问,--link 可以打通 

# 我们可以自定义一个网络!
使用方法:docker network create [选项] NETWORK

创建一个网络

选项:
      --attachable           启用手动容器附加
      --aux-address map      网络驱动程序使用的辅助IPv4或IPv6地址(默认map[])
      --config-from string   从中复制配置的网络
      --config-only          仅创建配置网络
  -d, --driver string        管理网络的驱动程序(默认为“bridge”)
      --gateway strings      主子网的IPv4或IPv6网关
      --ingress              创建Swarm路由网格网络
      --internal             限制对网络的外部访问
      --ip-range strings     从子范围中分配容器IP
      --ipam-driver string   IP地址管理驱动程序(默认为“default”)
      --ipam-opt map         设置IPAM驱动程序特定选项(默认map[])
      --ipv6                 启用IPv6网络
      --label list           在网络上设置元数据
  -o, --opt map              设置驱动程序特定选项(默认map[])
      --scope string         控制网络的范围
      --subnet strings       以CIDR格式表示的子网,代表一个网络段

 # 自定义网络
 # --driver bridge
 # --subnet 192.168.0.0/16
 # --gateway 192.168.0.1
 ➜  ~ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
4ed12b7f1bedf09a3469308939dfba71ab087cb5172d9d67b2a9fff11c6f89f3
➜  ~ docker network ls
NETWORK ID     NAME                 DRIVER    SCOPE
566cbd282a97   bridge               bridge    local
e093e1efed2a   host                 host      local
abec04ae3095   immich-app_default   bridge    local
4ed12b7f1bed   mynet                bridge    local
e7eb5bc8ed59   none                 null      local
3439b65e721b   somenetwork          bridge    local

image-20230609234514666

创建容器测试自定义网络

➜  ~ docker run -d -P --name tomcat-net-01 --net mynet tomcat
560e86b2ae30645287ccb9bd91ad2297b5adcfede6ec22033c5dce5e13921a29
➜  ~ docker run -d -P --name tomcat-net-02 --net mynet tomcat
86175ec7bada8ae3b38d5c8218e9901c15cde799443afa5d6c6d09a98aafb1eb
➜  ~ docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "4ed12b7f1bedf09a3469308939dfba71ab087cb5172d9d67b2a9fff11c6f89f3",
        "Created": "2023-06-09T11:41:52.511781837-04:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "560e86b2ae30645287ccb9bd91ad2297b5adcfede6ec22033c5dce5e13921a29": {
                "Name": "tomcat-net-01",
                "EndpointID": "afb03a260c5929858aba234f9f240938f1cbcf23f21953f548ea890a8d647c4a",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "86175ec7bada8ae3b38d5c8218e9901c15cde799443afa5d6c6d09a98aafb1eb": {
                "Name": "tomcat-net-02",
                "EndpointID": "b70d1d1e490b2ec614723747014c175ac5bbc11ef82de99c358093ab3f8b8b28",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

# 自定义网络下,现在可以不使用--link直接ping通其他相同网段的主机名字了
➜  ~ docker exec -it tomcat-net-02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.065 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.067 ms
^C
--- tomcat-net-01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.065/0.067/0.070/0.002 ms

➜  ~ docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.071 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.085 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.081 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=4 ttl=64 time=0.088 ms
^C
--- tomcat-net-02 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.071/0.081/0.088/0.006 ms

网络连通

思考,见下图假设docker0下的tomcat-01容器想要ping通mynet下面的tomcat-net-01,需要如何操作

image-20230610002855621

这时候就要用到 docker network connect 命令

connet 帮助命令
docker network connect --help
使用方法:docker network connect [选项] NETWORK CONTAINER

将容器连接到网络

选项:
      --alias strings           为容器添加网络范围的别名
      --driver-opt strings      网络的驱动程序选项
      --ip string               IPv4地址(例如,“172.30.100.104”)
      --ip6 string              IPv6地址(例如,“2001:db8::33”)
      --link list               添加到另一个容器的链接
      --link-local-ip strings   为容器添加链接本地地址

测试

# 打通tomcat-172-01 到 tomcat-net-01 
# 创建一个172网络,并在此下创建两个tomcat-172-01/02容器
➜  ~ docker network create --driver bridge --subnet 172.12.0.0/16 --gateway 172.12.0.1 172net
c5577fe012e3a07a804eba11f8dac994a3a2a290b6d1757e18cda298849dcd2a
➜  ~ docker run -d -P --name tomcat-172-01 --net 172net tomcat
fa95033579d90764051507a81e7f857c0c0c6fc37e286721bfe37663b929709a
➜  ~ docker run -d -P --name tomcat-172-02 --net 172net tomcat
4b9c59bd31a19d3bb85a31281b80475cd007c7e88d5b9828c1f1eac7a3d4ba35
➜  ~ docker network inspect 172net
[
    {
        "Name": "172net",
        "Id": "c5577fe012e3a07a804eba11f8dac994a3a2a290b6d1757e18cda298849dcd2a",
        "Created": "2023-06-09T12:47:14.618368071-04:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.12.0.0/16",
                    "Gateway": "172.12.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "4b9c59bd31a19d3bb85a31281b80475cd007c7e88d5b9828c1f1eac7a3d4ba35": {
                "Name": "tomcat-172-02",
                "EndpointID": "45e1ccbcf92536a51dfe20d433e8ffa149d8d6816ace0ff7ad087e64a29a14a2",
                "MacAddress": "02:42:ac:0c:00:03",
                "IPv4Address": "172.12.0.3/16",
                "IPv6Address": ""
            },
            "fa95033579d90764051507a81e7f857c0c0c6fc37e286721bfe37663b929709a": {
                "Name": "tomcat-172-01",
                "EndpointID": "c667b73be3631050f26c790cdcebe4df830cdd37bc5e7584b2183a623f6686be",
                "MacAddress": "02:42:ac:0c:00:02",
                "IPv4Address": "172.12.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

# 连通mynet网络与172net下面的tomcat-172-01
➜  ~ docker network connect mynet tomcat-172-01

#我们发现mynet直接把tocmat-172-01加进来了,相当于给tomcat-172-01添加了一个网卡
➜  ~ docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "4ed12b7f1bedf09a3469308939dfba71ab087cb5172d9d67b2a9fff11c6f89f3",
        "Created": "2023-06-09T11:41:52.511781837-04:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "560e86b2ae30645287ccb9bd91ad2297b5adcfede6ec22033c5dce5e13921a29": {
                "Name": "tomcat-net-01",
                "EndpointID": "afb03a260c5929858aba234f9f240938f1cbcf23f21953f548ea890a8d647c4a",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "86175ec7bada8ae3b38d5c8218e9901c15cde799443afa5d6c6d09a98aafb1eb": {
                "Name": "tomcat-net-02",
                "EndpointID": "b70d1d1e490b2ec614723747014c175ac5bbc11ef82de99c358093ab3f8b8b28",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            },
            "fa95033579d90764051507a81e7f857c0c0c6fc37e286721bfe37663b929709a": {
                "Name": "tomcat-172-01",
                "EndpointID": "a354c0bfadba5fbe5721d97db1645873e87039ded4c68a07593ed97a7c5eebd1",
                "MacAddress": "02:42:c0:a8:00:04",
                "IPv4Address": "192.168.0.4/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

# 这时候就打通tomcat-172-01 到 tomcat-net-01 
➜  ~ docker exec -it tomcat-172-01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.093 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.068 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.121 ms
^C
--- tomcat-net-01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.068/0.094/0.121/0.021 ms

总结,如果docker中涉及到跨网络操作,就需要用到 docker network connect命令

实战:redis集群部署

image-20230610010351228

# 创建redis集群网卡
➜  ~ docker network create redis --subnet 172.16.38.0/16
21a052aa1f7c06dc2934e2bc39a032d3e216861bfc9e38287c9396230b71df5f

# 通过脚本创建6个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

这段代码使用Shell脚本语言编写,它的作用是在循环中创建6个Redis节点,并为每个节点生成一个配置文件。具体分析如下:

​```
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
​```

1. for port in $(seq 1 6); \:这一行代码使用Shell的for循环语句,循环变量port的值从1到6。\表示这一行代码还没有结束,下一行代码是它的延续。

2. do \:这一行代码表示循环体的开始。

3. mkdir -p /mydata/redis/node-${port}/conf:这一行代码使用mkdir命令创建一个名为/mydata/redis/node-${port}/conf的目录。${port}是一个变量,它的值是循环变量port的值。

4. touch /mydata/redis/node-${port}/conf/redis.conf:这一行代码使用touch命令创建一个名为/mydata/redis/node-${port}/conf/redis.conf的空文件。

5. cat << EOF >/mydata/redis/node-${port}/conf/redis.conf:这一行代码使用cat命令将下面的多行文本输出到名为/mydata/redis/node-${port}/conf/redis.conf的文件中。<< EOF表示下面的多行文本是输入流的结束标记。

6. port 6379:这一行代码表示Redis节点的端口号为6379。

7. bind 0.0.0.0:这一行代码表示Redis节点绑定所有可用的IP地址。

8. cluster-enabled yes:这一行代码表示启用Redis集群模式。

9. cluster-config-file nodes.conf:这一行代码表示Redis集群配置文件的名称为nodes.conf。

10. cluster-node-timeout 5000:这一行代码表示Redis集群节点超时时间为5000毫秒。

11. cluster-announce-ip 172.38.0.1${port}:这一行代码表示Redis节点的IP地址为172.38.0.1${port}${port}是一个变量,它的值是循环变量port的值。

12. cluster-announce-port 6379:这一行代码表示Redis节点的公开端口号为6379。

13. cluster-announce-bus-port 16379:这一行代码表示Redis节点的集群总线端口号为16379。

14. appendonly yes:这一行代码表示启用Redis的AOF(Append Only File)持久化模式。
1
15. EOF:这一行代码表示输入流的结束标记。

16. done:这一行代码表示循环体的结束。

因此,这段代码的作用是在循环中创建6个Redis节点,并为每个节点生成一个配置文件。这些节点将在不同的端口上运行,并启用Redis集群模式和AOF持久化模式。这个脚本可以用于快速部署Redis集群。

# 检查节点信息
➜  ~ cd /mydata/redis/
➜  redis ls
node-1  node-2  node-3  node-4  node-5  node-6

#启动redis
# redis 批量启动脚本
for port in $(seq 1 6); \
do \
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.16.38.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
done

0f31ef8b230588be78a41888303117cf7f562f307d1cb627775a9da72b5ccdbd
086ae73698235881d9584e61927c6a2c2944ebdb511a85a280bfaf2a0f9dab3f
83a4d820c55baec833224affeb0745545e97284dfb2f21d77f34c2365eca36b4
c814e511ba3ba48d2e7dbbb5f24a935cfc09c156240dbd77c37b1e5ff49313ea
afd4713b5d308a4ea2e29d330d677f2f00dc66055b15407432f0f412a9ec149c
b5ad1b64a19ac76b4e0223e17fa75fde01e843876d78657d87d345cd3c62d397

# 进入容器创建集群
➜  redis docker exec -it redis-1 /bin/sh
/data # ls
appendonly.aof  nodes.conf
/data # redis-cli --cluster create 172.16.38.11:6379 172.16.38.12:63
79 172.16.38.13:6379 172.16.38.14:6379 172.16.38.15:6379 172.16.38.1
6:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.16.38.15:6379 to 172.16.38.11:6379
Adding replica 172.16.38.16:6379 to 172.16.38.12:6379
Adding replica 172.16.38.14:6379 to 172.16.38.13:6379
M: cbb624c2f0c9277fe5f61508c026e48e6ba01ae4 172.16.38.11:6379
   slots:[0-5460] (5461 slots) master
M: e4225901a8315ae2163994372bcd0580ef0fbfba 172.16.38.12:6379
   slots:[5461-10922] (5462 slots) master
M: 1121c13f2a53e8fa76a02a26ed9e4e5c4145e9d8 172.16.38.13:6379
   slots:[10923-16383] (5461 slots) master
S: 8226536952f5d03a29fe0de04586821518a13938 172.16.38.14:6379
   replicates 1121c13f2a53e8fa76a02a26ed9e4e5c4145e9d8
S: c04cdc7806b5a61a3da7e5e2aabe4c1fcb8cd98a 172.16.38.15:6379
   replicates cbb624c2f0c9277fe5f61508c026e48e6ba01ae4
S: 435d8d999e18fe3016bd8e8522ba9a22d9b31b5e 172.16.38.16:6379
   replicates e4225901a8315ae2163994372bcd0580ef0fbfba
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
......................................

DockerCompose介绍

简介


Docker

DockerFile build run 手动操作,每个容器!

Docker Compose 来轻松高效的定义和运行容器的工具

官方介绍

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。它使用 YAML 文件来配置应用程序的服务,并可以同时启动、停止和重建多个 Docker 容器。Docker Compose 允许开发人员在单个文件中定义整个应用程序的架构,包括应用程序的各个服务之间的关系和依赖关系。

Docker Compose 可以帮助开发人员轻松地构建、部署和管理多容器 Docker 应用程序,而无需手动创建和管理每个容器。它可以自动化多个容器之间的通信和协作,使容器之间的交互更加容易和可靠。另外,Docker Compose 还可以通过简化应用程序的部署和管理,帮助开发人员提高生产力和效率。

总之,Docker Compose 是一个非常有用的工具,可以大大简化多容器 Docker 应用程序的构建、部署和管理过程。它不仅可以提高开发人员的生产力,还可以提高整个团队的协作效率和应用程序的可靠性。

三个步骤

Using Docker Compose is a three-step process:

  1. Define your app's environment with a Dockerfile so it can be reproduced anywhere.
  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
  3. Lastly, run docker compose up and Compose will start and run your entire app.

image-20230610105036753

理解

Compose 是 Docker 官方开源项目,需要自行安装!

DockerFile 让程序在任何地方运行. web, mysql.nginx...多个容器

services:
  web:
    build: .
    ports:
      - "8000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    depends_on:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
Compose :重要概念
  • services (web, redis, mysql)

  • project (一组关联的容器)

安装Compose

1、下载(cnetos)

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

2、安装

sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

体验Compose

第一步:定义程序依赖
# home目录下创建composetest并且进入,写入以下内容到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)

# 创建requirements.txt,并写入
flask
redis
第二步:Dockerfile
# 创建Dockerfile
# syntax=docker/dockerfile:1
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"]
第三步:使用Compose file定义服务
# 创建docker-compose.yml并写入
services:
  web:
    build: .
    ports:
      - "8000:5000"
  redis:
    image: "redis:alpine"
第四步:建立和运行
docker-compose up
[+] Running 7/7
 ✔ redis 6 layers [⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled              8.8s
   ✔ 8a49fdb3b6a5 Pull complete                                2.1s
   ✔ 2121af5b35c8 Pull complete                                2.2s
   ✔ 13ce36f68149 Pull complete                                2.4s
   ✔ d0786890719f Pull complete                                3.7s
   ✔ e0001f8e7e31 Pull complete                                3.8s
   ✔ 4ea079d1c234 Pull complete                                3.9s
[+] Building 130.5s (8/12)
 => [internal] load .dockerignore                                                                                                                                        0.0s
 => => transferring context: 2B                                                                                                                                          0.0s
 => [internal] load build definition from Dockerfile                                                                                                                     0.0s
 => => transferring dockerfile: 380B                                                                                                                                     0.0s
 => resolve image config for docker.io/docker/dockerfile:1                                                                                                              14.3s
 => docker-image://docker.io/docker/dockerfile:1@sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14                                                 2.0s
 => => resolve docker.io/docker/dockerfile:1@sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14                                                     0.0s
 => => sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14 8.40kB / 8.40kB                                                                           0.0s
 => => sha256:966d40f9ba8366e74c2fa353fc0bc7bbc167d2a0f3ad2420db8b9e633049462d 482B / 482B                                                                               0.0s
 => => sha256:dbdd11720762ad504260c66161c964e59eba06b95a7aa64a68634b598a830a91 2.90kB / 2.90kB                                                                           0.0s
 => => sha256:a47ff7046597eea0123ea02817165350e3680f75000dc5d69c9a310258e1bedd 11.55MB / 11.55MB                                                                         1.6s
 => => extracting sha256:a47ff7046597eea0123ea02817165350e3680f75000dc5d69c9a310258e1bedd                                                                                0.3s
 => [internal] load metadata for docker.io/library/python:3.7-alpine                                                                                                     3.7s
 => [1/6] FROM docker.io/library/python:3.7-alpine@sha256:c0bbae8d4baab5783d172773bce4e2c9e3fadd8e186b11e3e7b4157d6a6d04d7                                               3.1s
 => => resolve docker.io/library/python:3.7-alpine@sha256:c0bbae8d4baab5783d172773bce4e2c9e3fadd8e186b11e3e7b4157d6a6d04d7                                               0.0s
 => => sha256:c0bbae8d4baab5783d172773bce4e2c9e3fadd8e186b11e3e7b4157d6a6d04d7 1.65kB / 1.65kB                                                                           0.0s
 => => sha256:beb8716a0c793a23e2462840909b5cd7702b39e6637981c0b1b7636086f64c9e 1.37kB / 1.37kB                                                                           0.0s
 => => sha256:69e6ede5bc7b36564e320f406aa459d7f7f47ce39e14a571cd916695b24677dd 6.87kB / 6.87kB                                                                           0.0s
 => => sha256:0357922e53aa8671e175f58d46bfd245908047b81e66370f634863785fe0c70e 622.30kB / 622.30kB                                                                       0.9s
 => => sha256:b25bf28fb2fc0d4e6b1aecbcc1eda4af8dc4d8499b3d93ef24a4f31d38b6a870 13.12MB / 13.12MB                                                                         2.0s
 => => sha256:c3653cf04d850e670635eec7da3a3500c4da02f7c1479cccaf1c6ff97ae33c0e 243B / 243B                                                                               0.7s
 => => sha256:c6c48565aa01c87cdea75bc2abdda29fd86cab13ad23ad15dc847056a9a305ee 2.85MB / 2.85MB                                                                           1.4s
 => => extracting sha256:0357922e53aa8671e175f58d46bfd245908047b81e66370f634863785fe0c70e                                                                                0.2s
 => => extracting sha256:b25bf28fb2fc0d4e6b1aecbcc1eda4af8dc4d8499b3d93ef24a4f31d38b6a870                                               [+] Building 130.7s (8/12)                                                                                                                                                                                   => [internal] load .dockerignore                                                                                                                                        0.0s                                => => transferring context: 2B                                                                                                                                          0.0s                                => [internal] load build definition from Dockerfile                                                                                                                     0.0s                                => => transferring dockerfile: 380B                                                                                                                                     0.0s                                => resolve image config for docker.io/docker/dockerfile:1                                                                                                              14.3s                                => docker-image://docker.io/docker/dockerfile:1@sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14                                                 2.0s
 => => resolve docker.io/docker/dockerfile:1@sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14                                                     0.0s
 => => sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14 8.40kB / 8.40kB                                                                           0.0s
 => => sha256:966d40f9ba8366e74c2fa353fc0bc7bbc167d2a0f3ad2420db8b9e633049462d 482B / 482B                                                                               0.0s
 => => sha256:dbdd11720762ad504260c66161c964e59eba06b95a7aa64a68634b598a830a91 2.90kB / 2.90kB                                                                           0.0s
 => => sha256:a47ff7046597eea0123ea02817165350e3680f75000dc5d69c9a310258e1bedd 11.55MB / 11.55MB                                                                         1.6s
 => => extracting sha256:a47ff7046597eea0123ea02817165350e3680f75000dc5d69c9a310258e1bedd                                                                                0.3s
 => [internal] load metadata for docker.io/library/python:3.7-alpine                                                                                                     3.7s
 => [1/6] FROM docker.io/library/python:3.7-alpine@sha256:c0bbae8d4baab5783d172773bce4e2c9e3fadd8e186b11e3e7b4157d6a6d04d7                                               3.1s
 => => resolve docker.io/library/python:3.7-alpine@sha256:c0bbae8d4baab5783d172773bce4e2c9e3fadd8e186b11e3e7b4157d6a6d04d7                                               0.0s
 => => sha256:c0bbae8d4baab5783d172773bce4e2c9e3fadd8e186b11e3e7b4157d6a6d04d7 1.65kB / 1.65kB                                                                           0.0s
 => => sha256:beb8716a0c793a23e2462840909b5cd7702b39e6637981c0b1b7636086f64c9e 1.37kB / 1.37kB                                                                           0.0s
 => => sha256:69e6ede5bc7b36564e320f406aa459d7f7f47ce39e14a571cd916695b24677dd 6.87kB / 6.87kB                                                                           0.0s
 => => sha256:0357922e53aa8671e175f58d46bfd245908047b81e66370f634863785fe0c70e 622.30kB / 622.30kB                                                                       0.9s
 => => sha256:b25bf28fb2fc0d4e6b1aecbcc1eda4af8dc4d8499b3d93ef24a4f31d38b6a870 13.12MB / 13.12MB                                                                         2.0s
 => => sha256:c3653cf04d850e670635eec7da3a3500c4da02f7c1479cccaf1c6ff97ae33c0e 243B / 243B                                                                               0.7s
 => => sha256:c6c48565aa01c87cdea75bc2abdda29fd86cab13ad23ad15dc847056a9a305ee 2.85MB / 2.85MB                                                                           1.4s
 => => extracting sha256:0357922e53aa8671e175f58d46bfd245908047b81e66370f634863785fe0c70e                                                                                0.2s
 => => extracting sha256:b25bf28fb2fc0d4e6b1aecbcc1eda4af8dc4d8499b3d93ef24a4f31d38b6a870                                                                                0.6s
 => => extracting sha256:c3653cf04d850e670635eec7da3a3500c4da02f7c1479cccaf1c6ff97ae33c0e                                                                                0.0s
 => => extracting sha256:c6c48565aa01c87cdea75bc2abdda29fd86cab13ad23ad15dc847056a9a305ee                                                                                0.3s
[+] Building 130.8s (8/12)
 => [1/6] FROM docker.io/library/python:3.7-alpine@sha256:c0b  3.1s  => => resolve docker.io/library/python:3.7-alpine@sha256:c0b  0.0s
 => => sha256:c0bbae8d4baab5783d172773bce4e2c 1.65kB / 1.65kB  0.0s  => => sha256:beb8716a0c793a23e2462840909b5cd 1.37kB / 1.37kB  0.0s  => => sha256:69e6ede5bc7b36564e320f406aa459d 6.87kB / 6.87kB  0.0s
 => => sha256:0357922e53aa8671e175f58d46b 622.30kB / 622.30kB  0.9s  => => sha256:b25bf28fb2fc0d4e6b1aecbcc1eda 13.12MB / 13.12MB  2.0s  => => sha256:c3653cf04d850e670635eec7da3a3500c4d 243B / 243B  0.7s
 => => sha256:c6c48565aa01c87cdea75bc2abdda29 2.85MB / 2.85MB  1.4s  => => extracting sha256:0357922e53aa8671e175f58d46bfd2459080  0.2s  => => extracting sha256:b25bf28fb2fc0d4e6b1aecbcc1eda4af8dc4  0.6s
 => => extracting sha256:c3653cf04d850e670635eec7da3a3500c4da  0.0s [+] Building 251.9s (8/12)
[+] Building 455.6s (8/12)
 => => sha256:beb8716a0c793a23e2462840909b5cd 1.37kB / 1.37kB  0.0s  => => sha256:69e6ede5bc7b36564e320f406aa459d 6.87kB / 6.87kB  0.0s  => => sha256:0357922e53aa8671e175f58d46b 622.30kB / 622.30kB  0.9s
 => => sha256:b25bf28fb2fc0d4e6b1aecbcc1eda 13.12MB / 13.12MB  2.0sy => => sha256:c3653cf04d850e670635eec7da3a3500c4d 243B / 243B  0.7s  => => sha256:c6c48565aa01c87cdea75bc2abdda29 2.85MB / 2.85MB  1.4s
 => => extracting sha256:0357922e53aa8671e175f58d46bfd2459080  0.2s
 => => extracting sha256:b25bf28fb2fc0d4e6b1aecbcc1eda4af8dc4  0.6s
 => => extracting sha256:c3653cf04d850e670635eec7da3a3500c4da  0.0s
 => => extracting sha256:c6c48565aa01c87cdea75bc2abdda29fd86c  0.3s
 => [internal] load build context                              0.0s
 => => transferring context: 1.31kB                            0.0s
 => [2/6] WORKDIR /code                                        0.1s
 => [3/6] RUN apk add --no-cache gcc musl-dev linux-headers  432.1s
 => => # _64/APKINDEX.tar.gz
 => => # fetch https://dl-cdn.alpinelinux.org/alpine/v3.18/communit
 => => # (1/13) Installing libgcc (12.2.1_git20220924-r10)
 => => # (2/13) Installing libstdc++ (12.2.1_git20220924-r10)
 => => # (3/13) Installing zstd-libs (1.5.5-r4)
 => => # (6/13) Installing libatomic (12.2.1_git20220924-r10)
 => => # (7/13) Installing gmp (6.2.1-r3)
 => => # (8/13) Installing isl26 (0.26-r1)
 => => # (9/13) Installing mpfr4 (4.2.0-r3)
 => => # (10/13) Installing mpc1 (1.3.1-r1)
 => => # (11/13) Installing gcc (12.2.1_git20220924-r10)
 => => # (12/13) Installing linux
 => => # -headers (6.3-r0)
 [+] Building 2516.3s (13/13) FINISHED
 => [internal] load .dockerignore                              0.0s  => => transferring context: 2B                                0.0s  => [internal] load build definition from Dockerfile           0.0s
 => => transferring dockerfile: 380B                           0.0sb => resolve image config for docker.io/docker/dockerfile:1    26.8s  => CACHED docker-image://docker.io/docker/dockerfile:1@sha25  0.0s
 => [internal] load metadata for docker.io/library/python:3.7  1.0s  => [internal] load build context                              0.0s  => => transferring context: 370B                              0.0s
 => [1/6] FROM docker.io/library/python:3.7-alpine@sha256:c0b  0.0s  => CACHED [2/6] WORKDIR /code                                 0.0s  => [3/6] RUN apk add --no-cache gcc musl-dev linux-header  2403.6s
 => [4/6] COPY requirements.txt requirements.txt               0.0s
 => [5/6] RUN pip install -r requirements.txt                 83.6s
 => [6/6] COPY . .                                             0.0s
 => exporting to image                                         0.9s
 => => exporting layers                                        0.9s
 => => writing image sha256:f72dc09fb5b15628e7b270259ff9e2a15  0.0s
 => => naming to docker.io/library/composetest-web             0.0s
[+] Running 3/1
 ✔ Network composetest_default    Created                      0.2s
 ✔ Container composetest-redis-1  Created                      0.0s
 ✔ Container composetest-web-1    Created                      0.0s
Attaching to composetest-redis-1, composetest-web-1
composetest-redis-1  | 1:C 10 Jun 2023 07:01:27.987 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
composetest-redis-1  | 1:C 10 Jun 2023 07:01:27.987 # Redis version=7.0.11, bits=64, commit=00000000, modified=0, pid=1, just started
composetest-redis-1  | 1:C 10 Jun 2023 07:01:27.987 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
composetest-redis-1  | 1:M 10 Jun 2023 07:01:27.987 * monotonic clock: POSIX clock_gettime
composetest-redis-1  | 1:M 10 Jun 2023 07:01:27.988 * Running mode=standalone, port=6379.
composetest-redis-1  | 1:M 10 Jun 2023 07:01:27.988 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
composetest-redis-1  | 1:M 10 Jun 2023 07:01:27.988 # Server initialized
composetest-redis-1  | 1:M 10 Jun 2023 07:01:27.988 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
composetest-redis-1  | 1:M 10 Jun 2023 07:01:27.989 * Ready to accept connections
composetest-web-1    |  * Serving Flask app 'app.py'
composetest-web-1    |  * Debug mode: off
composetest-web-1    | WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
composetest-web-1    |  * Running on all addresses (0.0.0.0)
composetest-web-1    |  * Running on http://127.0.0.1:5000
composetest-web-1    |  * Running on http://172.21.0.3:5000
composetest-web-1    | Press CTRL+C to quit
omposetest-web-1     | 172.21.0.1 - - [10/Jun/2023 07:06:20] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.21.0.1 - - [10/Jun/2023 07:06:22] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.21.0.1 - - [10/Jun/2023 07:06:23] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.21.0.1 - - [10/Jun/2023 07:06:24] "GET / HTTP/1.1" 200 -
效果
➜  ~ curl 172.21.0.3:5000
Hello World! I have been seen 1 times.
➜  ~ curl 172.21.0.3:5000
Hello World! I have been seen 2 times.
➜  ~ curl 172.21.0.3:5000
Hello World! I have been seen 3 times.
➜  ~ curl 172.21.0.3:5000
Hello World! I have been seen 4 times.

以前单个都是通过docker run 启动

docker-compose,通过编写yaml配置文件,可以一键启动/停止所有服务

yaml 规则

docker-compose.yaml 核心

官方详细用法

# 三层

version: '' #版本
services:   #服务
    服务1:web
        #服务配置
        images
        build
        network
    服务2:redis
        ...
#其它配置   卷/网络,全局规则
volmes:
config:
network:
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇