目录

一、docker离线安装

2.docker常用命令

二、docker制作系统服务

1.contes7快捷方式

2.麒麟v10操作系统 docker快捷方式启动

三、离线安装nginx

四、安装mysql

1.单点mysql

2.主从mysql

五、安装docker-compose

1.从github上下载docker-compose二进制文件安装

2.docker-compose常用命令

六、Docker容器监控之 CAdvisor+InfluxDB+Granfana

七、Docker轻量级可视化工具Portainer

八、docker-compose 部署 NGINX + PHP+MySQL

九、docker网络详解

3. 自定义网络(推荐使用)

4. 网络连通


一、docker离线安装

1.安装步骤

#1. 下载 Docker 二进制文件(离线安装包)
#下载地址:https://download.docker.com/linux/static/stable/x86_64/

#2. 通过xftp工具将 docker-18.06.3-ce.tgz 上传到服务器上
#3. 解压安装包
tar zxf docker-18.06.3-ce.tgz

#4. 将docker 相关命令拷贝到 /usr/bin,方便直接运行命令
sudo cp docker/* /usr/bin/

#5. 启动Docker守护程序
sudo dockerd &

#6. 验证是否安装成功,执行docker info命令,若正常打印版本信息则安装成功。
docker info

2.docker常用命令

docker笔记_容器

官网docker | Docker Documentation

Docker容器的一些命令按功能分类大致如下

#打包

docker save easzlab/k8s-cache:1.16.0  > /root/k8s-cache:1.16.0.tar

#加载包
docker load -i /root/k8s-cache:1.16.0.tar


Docker环境信息   info、version
镜像仓库命令      login、logout、pull、push、search
镜像管理          build、images、import、load、rmi、save、tag、commit
容器生命周期管理  create、exec、kill、pause、restart、rm、run、start、stop、unpause
容器运维操作      attach、export、inspect、port、ps、rename、stats、top、wait、cp、diff、update
容器资源管理      volume、network
系统信息日志      events、history、logs
1.events打印容器的实时系统事件
2.history 打印出指定镜像的历史版本信息
3.logs打印容器中进程的运行日志

docker --help       #查看docker命令
docker info         #docker 详细信息,镜像和容器
docker version      #查看docker版本
帮助文档地址:https://docs.docker.com/reference/

docker images # 查看docker镜像;
# 具体列解释含义:
REPOSITORY  #镜像仓库源                
TAG         #镜像的标签                 
IMAGE ID    #镜像id            
CREATED     #创建时间             
SIZE        #大小

docker images -a            #列出本地所有的镜像
docker images -q            #只显示镜像ID
docker images --digests     #显示镜像的摘要信息
docker images --no-trunc    #显示完整的镜像信息

docker search tomcat    # 从Docker Hub上查找tomcat镜像
STARS:                 # 关注度
docker search --filter=stars=300 tomcat     #从Docker Hub上查找关注度大于300的tomcat镜像

docker pull tomcat      #从Docker Hub上下载tomcat镜像,默认是最新版本。等价于:docker pull tomcat:latest
docker pull tomcat:8  # 选择指定版本下载

#单个镜像删除,相当于:docker rmi java:latest
docker rmi java
#强制删除(删除正在运行的镜像,注:以后台方式运行的不能被强制删除)
docker rmi -f java
#多个镜像删除,不同镜像间以空格间隔
docker rmi -f java tomcat nginx
#删除本地全部镜像
docker rmi -f $(docker images -q)

# 查看正在运行的容器
docker ps
# 查看所有容 包括停止的容器
docker ps -a
# -q参数,只显示container id
docker ps -q
# 查看容器详细信息
docker inspect demo1

容器启动与停止

#新建并启动容器,参数:-i  以交互模式运行容器;-t  为容器重新分配一个伪输入终端;--name  为容器指定一个名称
docker run -i -t --name mycentos 镜像名称/镜像ID

#后台启动容器,参数:-d  已守护方式启动容器
docker run -d mycentos

#启动止容器
docker start 容器id
# 重启容器
docker restart 容器id
# 关闭容器
docker kill 容器id
docker stop 容器id

-t 参数让Docker分配一个伪终端并绑定到容器的标准输入上
-i 参数则让容器的标准输入保持打开。
-c 参数用于给运行的容器分配cpu的shares值
-m 参数用于限制为容器的内存信息,以 B、K、M、G 为单位
-v 参数用于挂载一个volume,可以用多个-v参数同时挂载多个volume
-p 参数用于将容器的端口暴露给宿主机端口 格式:host_port:container_port 或者 host_ip:host_port:container_port
--name 容器名称
--net 容器使用的网络
-d 创建一个后台运行容器


容器进入与退出

#使用run方式在创建时进入
docker run -it centos /bin/bash
#关闭容器并退出
exit
#仅退出容器,不关闭
快捷键:Ctrl + P + Q
快捷键:Ctrl + Shift + P + Q


容器进程

#top支持 ps 命令参数,格式:docker top [OPTIONS] CONTAINER [ps OPTIONS]
#列出redis容器中运行进程
docker top tomcat
#查看所有运行容器的进程信息
for i in  `docker ps |grep Up|awk '{print $1}'`;do echo \ &&docker top $i; done


容器日志

# 查看redis容器日志,默认参数
docker logs tomcat
# 查看redis容器日志,参数:-f  跟踪日志输出;-t   显示时间戳;--tail  仅列出最新N条容器日志;
docker logs -f -t --tail=20 redis
# 查看容器redis从2021年08月10日后的最新10条日志。
docker logs --since="2021-08-10" --tail=10 redis


容器内拷贝文件到主机

docker cp 容器id:容器内路径  目的主机路径

二、docker制作系统服务
 

1.contes7快捷方式

#杀掉docker
pkill -9 docker

# 在 /usr/lib/systemd/system/ 目录下创建docker.service 文件
cat > /usr/lib/systemd/system/docker.service <<EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
 
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
 
[Install]
WantedBy=multi-user.target
EOF


#添加docker仓库
mkdir -p /etc/docker/
cat >/etc/docker/daemon.json<<EOF
{
    "registry-mirrors": ["https://gv33cz42.mirror.aliyuncs.com", "https://registry.docker-cn.com", "https://docker.mirrors.ustc.edu.cn", "https://dockerhub.azk8s.cn"],
    "exec-opts": ["native.cgroupdriver=systemd"],
    "max-concurrent-downloads": 20,
    "live-restore": true,
    "storage-driver": "overlay2",
    "max-concurrent-uploads": 10,
    "debug": true,
    "log-opts": {
    "max-size": "100m",
    "max-file": "10"
    }
}
EOF


#启动
systemctl daemon-reload && systemctl restart docker && systemctl enable docker && systemctl status docker|grep Active

2.麒麟v10操作系统 docker快捷方式启动

#杀掉docker
pkill -9 docker


cat > /usr/lib/systemd/system/docker.service <<EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF

#启动

systemctl daemon-reload && systemctl restart docker && systemctl enable docker && systemctl status docker|grep Active

三、离线安装nginx

#下载高版本nginx

docker pull nginx:1.23.2

#将镜像保存为本地tar文件

docker save nginx:1.23.2 > /root/nginx-1.23.2.tar

#使用load加载tar文件

docker load -i  /root/nginx-1.23.2.tar

#之后的文件就放这里面,对 docker 里 Nginx 对应的目录进行映射,就不用改文件进到容器里了

mkdir -p /data/nginx/{conf,conf.d,html,logs}


#把 nginx.conf 文件和 conf.d 里的 default.conf 复制到对应文件夹放好,后面就是修改了
cat > /data/nginx/conf/nginx.conf <<EOF
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;
}

EOF



cat > /data/nginx/conf.d/default.conf <<EOF
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

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

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }



    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}


}

EOF



cat > /data/nginx/html/index.html <<EOF
<!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>nginx-v01</h1>
</body>
</html>

EOF

#部署nginx

docker run  --name myNginx -d -p 80:80 \
-v /data/nginx/html:/usr/share/nginx/html \
-v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /data/nginx/conf.d:/etc/nginx/conf.d  \
-v /data/nginx/logs:/var/log/nginx \
-v /etc/localtime:/etc/localtime:ro \
nginx:1.23.2

四、安装mysql

1.单点mysql

mkdir -p /data/mysql/{log,data,conf}



cat > /data/mysql/conf/my.cnf <<EOF
[client]
default_character_set=utf8
[mysqld]
socket=/var/run/mysqld/mysqld.sock
collation_server = utf8_general_ci
character_set_server = utf8
#设置不区分大小写
lower_case_table_names = 1
EOF
 

#运行
docker run -d -p 3306:3306 --privileged=true \
-v /data/mysql/log:/var/log/mysql \
-v /data/mysql/data:/var/lib/mysql \
-v /data/mysql/conf:/etc/mysql/conf.d \
-v /etc/localtime:/etc/localtime:ro \
-e MYSQL_ROOT_PASSWORD=123456 \
--name mysql \
mysql:5.7




#查看
docker ps |grep mysql

#验证

#进入 mysql-master
docker exec -it mysql /bin/bash

#登入
mysql -uroot -proot


#查看字符集
SHOW VARIABLES LIKE 'character%';

2.主从mysql

a.安装 主mysql

#新建目录
mkdir -p /mydata/mysql-master/{log,data,conf}
mkdir -p /mydata/mysql-slave/{log,data,conf}


#创建主mysql
docker run -d -p 3307:3306 --privileged=true \
-v /mydata/mysql-master/log:/var/log/mysql \
-v /mydata/mysql-master/data:/var/lib/mysql \
-v /mydata/mysql-master/conf:/etc/mysql \
-v /etc/localtime:/etc/localtime:ro \
-e MYSQL_ROOT_PASSWORD=root \
--name mysql-master \
mysql:5.7.30

#查看
docker ps


#主配置
cat > /mydata/mysql-master/conf/my.cnf<<EOF
[mysqld]
socket=/var/run/mysqld/mysqld.sock
## 同一局域网内注意要唯一
server-id=100  
## 开启二进制日志功能,可以随便取(关键)
log-bin=mysql-bin
EOF
 
#重启
docker restart mysql-master
 
#查看
docker ps
 
#进入 mysql-master
docker exec -it mysql-master /bin/bash
 
#登入
mysql -uroot -proot


#创建同步用户,授权
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
flush privileges;


#在主节点查看id
show master status;

b.安装 从mysql

#新建从服务器容器实例3308
docker run -d -p 3308:3306 --privileged=true \
-v /mydata/mysql-slave/log:/var/log/mysql \
-v /mydata/mysql-slave/data:/var/lib/mysql \
-v /mydata/mysql-slave/conf:/etc/mysql \
-v /etc/localtime:/etc/localtime:ro \
-e MYSQL_ROOT_PASSWORD=root \
--name mysql-slave \
mysql:5.7.30

#查看
docker ps

#从配置
cat > /mydata/mysql-slave/conf/my.cnf<<EOF
[mysqld]
socket=/var/run/mysqld/mysqld.sock
## 设置server_id,注意要唯一
server-id=101  
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave-bin   
## relay_log配置中继日志
relay_log=edu-mysql-relay-bin
EOF


#重启
docker restart mysql-slave

docker ps

#从mysql
docker exec -it mysql-slave /bin/bash

#登入mysql
mysql -uroot -proot




#在从数据库中配置主从复制 ip填写宿主机ip
change master to master_host='192.168.1.31', master_user='slave', master_password='123456', master_port=3307, master_log_file='mysql-bin.000004', master_log_pos=769, master_connect_retry=30;

#在从库 开启主从同步
start slave;

#在从库查看状态
show slave status \G;

五、安装docker-compose

1.从github上下载docker-compose二进制文件安装

#下载
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose



#下面无法下载,可以去百度网盘
链接:https://pan.baidu.com/s/1qE06PjPs9547dIhsMcp9iw?pwd=u6jr 
提取码:u6jr


#添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose

#测试安装结果
docker-compose --version

2.docker-compose常用命令

docker-compose 命令 --help                     获得一个命令的帮助
docker-compose up -d nginx                     构建启动nignx容器
docker-compose exec nginx bash                 登录到nginx容器中
docker-compose down                            此命令将会停止 up 命令所启动的容器,并移除网络
docker-compose ps                              列出项目中目前的所有容器
docker-compose restart nginx                   重新启动nginx容器
docker-compose build nginx                     构建镜像 
docker-compose build --no-cache nginx          不带缓存的构建
docker-compose top                             查看各个服务容器内运行的进程 
docker-compose logs -f nginx                   查看nginx的实时日志
docker-compose images                          列出 Compose 文件包含的镜像
docker-compose config                          验证文件配置,当配置正确时,不输出任何内容,当文件配置错误,输出错误信息。 
docker-compose events --json nginx             以json的形式输出nginx的docker日志
docker-compose pause nginx                     暂停nignx容器
docker-compose unpause nginx                   恢复ningx容器
docker-compose rm nginx                        删除容器(删除前必须关闭容器,执行stop)
docker-compose stop nginx                      停止nignx容器
docker-compose start nginx                     启动nignx容器
docker-compose restart nginx                   重启项目中的nignx容器
docker-compose run --no-deps --rm php-fpm php -v   在php-fpm中不启动关联容器,并容器执行php -v 执行完成后删除容器

六、Docker容器监控之 CAdvisor+InfluxDB+Granfana

1.新建目录

mkdir /mydocker/cig

2.新建3件套组合的 docker-compose.yml

vim /mydocker/cig/docker-compose.yml

version: '3.1'
 
volumes:
  grafana_data: {}
 
services:
 influxdb:
  image: tutum/influxdb:0.9
  restart: always
  environment:
    - PRE_CREATE_DB=cadvisor
  ports:
    - "8083:8083"
    - "8086:8086"
  volumes:
    - ./data/influxdb:/data
 
 cadvisor:
  image: google/cadvisor
  links:
    - influxdb:influxsrv
  command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
  restart: always
  ports:
    - "8080:8080"
  volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:rw
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro
 
 grafana:
  user: "104"
  image: grafana/grafana
  user: "104"
  restart: always
  links:
    - influxdb:influxsrv
  ports:
    - "3000:3000"
  volumes:
    - grafana_data:/var/lib/grafana
  environment:
    - HTTP_USER=admin
    - HTTP_PASS=admin
    - INFLUXDB_HOST=influxsrv
    - INFLUXDB_PORT=8086
    - INFLUXDB_NAME=cadvisor
    - INFLUXDB_USER=root
    - INFLUXDB_PASS=root

3.启动

docker-compose up -d

详细配置参考

Docker学习22 - Docker容器监控之 CAdvisor+InfluxDB+Granfana - suphowe

七、Docker轻量级可视化工具Portainer

1.部署

docker run -d -p 8000:8000 -p 9000:9000 --name portainer     --restart=always     -v /var/run/docker.sock:/var/run/docker.sock     -v portainer_data:/data     portainer/portainer

2.选择local选项卡后本地docker详细信息展示

八、docker-compose 部署 NGINX + PHP+MySQL

1.创建数据文件夹

mkdir /data
cd /data
mkdir -p mysql/conf.d
mkdir -p mysql/data
mkdir -p nginx/conf.d
mkdir -p nginx/log
mkdir -p php/conf.d
mkdir www

2.nginx配置文件

sudo docker run --name nginx -d nginx
#复制出来配置文件:
sudo docker cp nginx:/etc/nginx/conf.d/default.conf /data/nginx/conf.d/

3.创建php的Dockerfile:

cat /data/php/Dockerfile

FROM php:7.4-fpm
RUN apt-get update && apt-get install -y \
		libfreetype6-dev \
		libjpeg62-turbo-dev \
		libpng-dev \
		libvpx-dev libwebp-dev \
	&& docker-php-ext-configure gd  --with-webp=/usr/include/webp --with-jpeg=/usr/include --with-freetype=/usr/include/freetype2 \
	&& docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install mysqli \
    && docker-php-ext-install pdo_mysql

#打包镜像

docker build -t myphp:1.0 ./

4.复制出php的配置文件

sudo docker run --name php -d myphp:1.0
sudo docker cp php:/usr/local/etc/php/php.ini-production php/conf.d/php.ini

5.修改nginx/conf.d/default.conf

cat /data/nginx/conf.d/default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

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

    location / {
        root   /usr/share/nginx/html;
        index  index.php index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }



    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    
    location ~ \.php$ {
       root           /usr/share/nginx/html;
       fastcgi_pass   compose-php:9000;
       fastcgi_index  index.php;
       fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
       fastcgi_param  SCRIPT_NAME      $fastcgi_script_name;
       include        fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

6.复制数据库的配置文件

docker run --name mysql -d mysql:5.7
docker cp mysql:/etc/mysql/conf.d /data/mysql/

6.1删除之前部署的进程

docker kill $(docker ps -a |grep mysql)
docker kill $(docker ps -a |grep php)
docker kill $(docker ps -a |grep nginx)
docker rm $(docker ps -a |grep mysql)
docker rm $(docker ps -a |grep php)
docker rm $(docker ps -a |grep nginx)

7. cat /data/docker-compose.yaml

version: "3"
services:
  nginx:
    image: nginx:latest
    container_name: "compose-nginx"
    restart: always
    ports:
      - "80:80"
      - "443:443"
    environment:
      - TZ=Asia/Shanghai
    depends_on:
      - "php"
    volumes:
      - "/data/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf"
      - "/data/nginx/log:/var/log/nginx"
      - "/data/www:/usr/share/nginx/html"
    networks:
      - net-app
  php:
    image: myphp:1.0
    container_name: "compose-php"
    restart: always
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - "/data/www:/usr/share/nginx/html"
      - "/data/php/conf.d/php.ini:/usr/local/etc/php/php.ini"
    networks:
      - net-app
  mysql:
    image: mysql:5.7
    container_name: "compose-mysql"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: admin
      MYSQL_PASSWORD: admin
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/conf.d:/etc/mysql/conf.d
    networks:
      - net-app
networks:
    net-app:

8.启动

cd /data/

#启动
docker-compose up -d
#停止
docker-compose stop
#卸载
docker-compose down

9.浏览器访问

echo '<?php phpinfo();?>'> www/info.php

curl http://localhost/info.php

或浏览器打开访问

10.连接数据库:

sudo docker run -it --network data_net-app mysql:5.7 mysql -uroot -proot -hcompose-mysql

博客参考:

九、Docker网络详解

1. Docker网络模式

Docker默认提供了3种网络模式,生成容器时不指定网络模式下默认使用bridge桥接模式。

[root@haha docker_web]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
aa8a26ae1484   bridge    bridge    local
62cd016ed66a   host      host      local
fc650e2a675e   none      null      local

1.1 host模式

如果启动容器时使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
 

Namespace的简要说明:
Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。
一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的NetworkNamespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。


1.2 container模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信
1.3 none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
1.4 bridge模式

bridge模式是docker的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。bridge模式如下图所示:
 

docker笔记_运维_02

当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器都会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

docker笔记_mysql_03

docker笔记_mysql_04

从上图中我们可以看到,可以看到容器内部和Linux主机都会创建一个新的网卡,而这两个网卡都是成对的。使用的技术就是evth-pair。evth-pair 就是一对的虚拟设备接口,他们是成对出现的,一段连着协议,一段彼此相连。evth-pair充当一个桥梁,连接各种虚拟网络设备。

Docker容器完成bridge网络配置的过程如下:
1. 在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
2. Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以vethb22db1b4这样类似的名字命名,并将这个网络设备加入到docker0网桥中。
3. 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
 

   宿主机和Docker容器之间是可以进行网络连接的,同样的,Docker容器和容器之间也可以直接进行网络连接

[root@haha docker_web]# docker exec -it a52bd646da1f 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.193 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.134 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.132 ms

[root@haha docker_web]# docker exec -it 386ffc29485d ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.146 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.137 ms

容器1和容器2,都使用公用的路由器docker0。所有的容器在不指定网络情况下,都是由docker0路由的,Docker会给我们容器默认分配一个随机的可用IP地址,这些IP地址之间是可以进行网络交互的,交互模型图如下:

docker笔记_nginx_05

2. 容器互联

在微服务部署的场景下,注册中心是使用服务名来唯一识别微服务的,而我们上线部署的时候微服务对应的IP地址可能会改动,所以我们需要使用容器名来配置容器间的网络连接。使–link可以完成这个功能。

首先不设置–link的情况下,是无法通过容器名来进行连接的。centos02容器是可以直接ping通centos01的容器ip,但是无法ping通centos01的容器name:
 

[root@haha ~]# docker ps
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
c742968a290a   5d0da3dc9764   "/bin/bash"   9 seconds ago    Up 8 seconds              centos02
581740709b5e   5d0da3dc9764   "/bin/bash"   30 seconds ago   Up 28 seconds             centos01
[root@haha ~]#
[root@haha ~]# docker exec -it centos01 ip addr
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
34: eth0@if35: <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@haha ~]#
[root@haha ~]# docker exec -it centos02 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.102 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.135 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.137 ms
[root@haha ~]#
[root@haha ~]# docker exec -it centos02 ping centos01
ping: centos01: Name or service not known

添加参数 –link,可以通过容器name进行连接。centos03容器link到centos01,所以centos03可以直接通过ping centos01的容器名去ping通,但是反过来centos01去ping centos03的容器名是ping不通的。

[root@haha ~]# docker run -d -P -it --name centos03 --link centos01 5d0da3dc9764
a66f059fe26da45e5c59af03a2c33f429452a2dcf884ad5826fa0e3985ab3862
[root@haha ~]# docker ps
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
a66f059fe26d   5d0da3dc9764   "/bin/bash"   7 seconds ago    Up 5 seconds              centos03
c742968a290a   5d0da3dc9764   "/bin/bash"   11 minutes ago   Up 11 minutes             centos02
581740709b5e   5d0da3dc9764   "/bin/bash"   11 minutes ago   Up 11 minutes             centos01
[root@haha ~]#
[root@haha ~]# docker exec -it centos03 ping centos01
PING centos01 (172.17.0.2) 56(84) bytes of data.
64 bytes from centos01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from centos01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from centos01 (172.17.0.2): icmp_seq=3 ttl=64 time=0.076 ms
^C
[root@haha ~]#
[root@haha ~]# docker exec -it centos01 ping centos03
ping: centos03: Name or service not known

–link的原理就是在centos03容器的hosts文件中添加了要去link的centos01容器的容器名和ip地址映射。但是因为docker0不支持容器名访问,所以–link设置容器互连的方式也不再推荐使用了,更多地选择自定义网络。

docker笔记_容器_06

3. 自定义网络(推荐使用)

docker network 命令及经常使用到的命令:

docker network --help

 

docker笔记_容器_07

 如何自定义一个网络?

docker network create --help

docker笔记_容器_08

具体使用:

[root@haha ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
ed1c176a06d49da31969e229138ef5988a5fd9d2b2f2d2fc5ec1078be99a3d39
[root@haha ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
aa8a26ae1484   bridge    bridge    local
62cd016ed66a   host      host      local
ed1c176a06d4   mynet     bridge    local
fc650e2a675e   none      null      local

查看新创键的mynet详细信息:

docker笔记_容器_09

使用自定义网络创建容器后,相同网络name下的容器,不管是通过容器IP还是容器name,都可以进行网络通信

# 创建两个使用相同自定义网络的容器
[root@haha ~]# docker run -d -P --name centos-net-01 --net mynet -it 5d0da3dc9764 /bin/bash
[root@haha ~]# docker run -d -P --name centos-net-02 --net mynet -it 5d0da3dc9764 /bin/bash
[root@haha ~]#
[root@haha ~]# docker ps
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
2511566dd5f3   5d0da3dc9764   "/bin/bash"   4 seconds ago    Up 3 seconds              centos-net-02
924e92107f64   5d0da3dc9764   "/bin/bash"   23 seconds ago   Up 21 seconds             centos-net-01
a66f059fe26d   5d0da3dc9764   "/bin/bash"   43 minutes ago   Up 43 minutes             centos03
c742968a290a   5d0da3dc9764   "/bin/bash"   54 minutes ago   Up 54 minutes             centos02
581740709b5e   5d0da3dc9764   "/bin/bash"   55 minutes ago   Up 55 minutes             centos01

# 测试容器互连
[root@haha ~]# docker exec -it centos-net-01 ping centos-net-02
PING centos-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.689 ms
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.078 ms
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.097 ms
^C
[root@haha ~]# docker exec -it centos-net-01 ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.091 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.048 ms
64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=0.094 ms
^C

4. 网络连通

在没有使用connect命令的情况下,不同网络间的容器是无法进行网络连接的。

docker笔记_nginx_10

docker笔记_docker_11

不同Docker网络之间的容器想要连接的话,需要把该容器注册到另一个容器所在的网络上,使用docker connect命令。

docker network connect mynet centos01

connect设置成功后,我们可以看到新注册进来的容器信息:

docker笔记_mysql_12

接下来进行容器双向连接测试:

# centos-net-01 ping centos01,连接成功
[root@haha ~]# docker exec -it centos-net-01 ping centos01
PING centos01 (192.168.0.4) 56(84) bytes of data.
64 bytes from centos01.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.183 ms
64 bytes from centos01.mynet (192.168.0.4): icmp_seq=2 ttl=64 time=0.139 ms
64 bytes from centos01.mynet (192.168.0.4): icmp_seq=3 ttl=64 time=0.136 ms
^C
# centos01 ping centos-net-01,连接成功
[root@haha ~]# docker exec -it centos01 ping centos-net-01
PING centos-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.135 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.141 ms
^C
[root@haha ~]# 未连接到mynet的容器还是无法访问
[root@haha ~]# docker exec -it centos-net-01 ping centos02
ping: centos02: Name or service not known


感谢高过蓝天Docker网络详解_高过蓝天的云的博客