macvlan是一种网卡虚拟化技术,能够将一张网卡(Network Interface Card, NIC)虚拟出多张网卡,这意味着每个虚拟网卡都能拥有独立的MAC地址和IP地址,从而在系统层面表现为完全独立的网络接口。这些虚拟网卡可以直接连接到物理网络,就像是网络中单独的物理设备一样,而不像传统的网络桥接或VLAN那样需要一个共同的桥接接口来转发流量。可以简单理解为macvlan是docker容器中的一种网络模式,可以让容器直接连接到宿主机的物理网络。
Docker容器是一种轻量级、可移植的软件封装技术,它允许开发者将应用程序及其所有的依赖包打包到一个独立的、可运行的包中。这个包可以在任何安装了Docker引擎的系统上运行,无论该系统是在开发、测试还是生产环境中,保证了应用运行环境的一致性。Docker容器利用操作系统的Namespace和Control Groups等技术,实现了资源的隔离和限制,使得每个容器都像是运行在一个独立的系统中,但实际共享着宿主机的内核。

Bridge (桥接模式) ---默认模式
解释:Bridge模式是Docker的默认网络配置。每个使用此模式的容器都会得到一个独立的Network Namespace,Docker会为容器分配一个内部IP地址,并将其连接到一个名为docker0的虚拟网桥上。这意味着容器间可以相互通信,同时也能够通过宿主机的网络栈访问外部网络。
适用情况:当你需要容器之间能够直接通信,且容器需要访问互联网或者被外部网络访问时,使用Bridge模式最为常见。
Host (主机模式)
解释:在Host模式下,容器不会获得自己的Network Namespace,而是直接使用宿主机的网络堆栈。这意味着容器将共享宿主机的网络接口和端口,容器内的网络服务可以直接使用宿主机的IP地址和端口号对外提供服务。
适用情况:如果你的应用需要直接绑定到宿主机的网络接口,或者需要极低的网络延迟,可以考虑使用Host模式。但需要注意,这样做可能会导致安全风险和端口冲突问题。
None (无网络模式)
解释:None模式下,Docker不会为容器配置任何网络设施,容器将只有一个lo(loopback)接口,无法访问外部网络,也无法和其他容器通信,除非你手动配置网络。
适用情况:如果你的容器不需要网络连接,或者你计划完全自定义网络配置(例如,使用自定义网络接口或复杂的网络拓扑),可以选择None模式。
Container (容器模式)
解释:这种模式允许一个容器共享另一个容器的Network Namespace,而不是创建新的或使用宿主机的。这意味着两个容器将共享相同的网络配置,包括IP地址和端口空间。
适用情况:当多个容器需要共享相同的网络环境时,比如在Kubernetes中的Pods,所有容器需要共享同一套网络资源和配置时,这种模式非常有用。
Macvlan (MAC VLAN 模式)
Macvlan 是一种网络虚拟化技术,允许在单个物理网络接口上创建多个虚拟以太网接口(每个都有独立的MAC地址),这些虚拟接口可以直接连接到物理网络,仿佛是直接连接到交换机上的独立物理设备。在 Docker 中使用 macvlan 模式,可以为每个容器提供一个直接与物理网络相连的网络接口,绕过 Docker 默认的网络桥接,从而获得更低的网络延迟和更接近物理机的网络行为。这种模式非常适合需要直接与外部网络交互,且要求低延迟或特定网络配置的场景。
安装教程:https://docker-practice.github.io/zh-cn/install/ubuntu.html
安装完后一定要添加镜像源:

比如我在广州或东莞:
{
"registry-mirrors": ["https://cn-guangzhou.mirror.aliyuncs.com"]
}
基础操作:
nano daemon.json #进入文件,文件不存在时自动创建
ctrl + o 保存文件 ctrl + x 退出文件 rm -i 文件名 #删除文件
mkdir 目录名 #创建目录 rmdir 目录名 #删除目录
更改文件前建议备份文件:
- cp example.txt example.txt.backup #假设要编辑的文件名为
example.txt,cp命令创建一个副本- mv example.txt.backup example.txt #如果修改后的文件已经保存,你可以直接用mv将备份文件覆盖回去
- diff example.txt.example.txt.backup #如果你不确定是否需要完全恢复,或者想查看具体哪些地方发生了变化,可以使用
diff命令比较两个文件的差异,然后手动决定如何修改。
安装完上面后再拉取镜像
docker pull ubuntu #获取Ubuntu的最新长期支持版本(LTS)
docker pull ubuntu:20.04 #如果你需要特定版本,比如20.04
daemon.json是Docker守护进程(dockerd)的配置文件,它允许系统管理员自定义Docker守护程序的行为和参数。这个文件通常位于/etc/docker/目录下,并且在Docker Engine 1.12及更高版本中可以被使用。docker服务使用 systemctl start docker 命令启动失败时,考虑daemon.json的配置是否正确。作用:
网络配置:通过
daemon.json,你可以配置Docker的网络设置,比如桥接网络的子网、网关等。日志记录:配置Docker日志的驱动、日志级别以及日志输出目标,比如将日志发送到syslog或文件系统。
存储驱动:选择或修改Docker使用的存储驱动(如overlay2、aufs等),这对于容器的存储性能和管理非常重要。
镜像加速:对于中国用户而言,可以在该文件中配置镜像加速器地址,以加快从Docker Hub拉取镜像的速度。
注册表镜像认证:配置私有注册表的认证信息,使得Docker守护进程能够无需交互式输入凭据就能拉取私有镜像。
TLS配置:设定Docker守护进程的TLS加密和证书路径,增强Docker API的安全性。
资源限制:例如内存、CPU使用限制,可以在这里全局设置Docker容器可使用的最大资源量。
live-restore:设置容器在Docker守护进程重启时不退出,保持容器持续运行。
其他高级选项:包括IPv6支持、容器默认的隔离技术、容器标签策略等。
- 查看信息 --------------------------------------------------------------------------
-
- docker ps # 查看正在运行的容器
- docker ps -a # 查看所有容器
-
- #查看容器相关信息(推荐使用这个)
- #打印网络名称、容器名称、主机名及对应的IP地址
- docker inspect --format '{{range $key, $value := .NetworkSettings.Networks}}{{$key}}: {{$.Name}} - {{$.Config.Hostname}} - {{$value.IPAddress}}{{println}}{{end}}' 容器名/ID
-
- #查看存在的网络
- docker network ls
-
- #查看某个网络下连接的容器
- docker network inspect 网络名或ID
-
- #查看容器连接的网络
- docker inspect 容器名/ID
-
- ip addr show #列出系统中所有网络接口,包括IP地址、子网掩码、广播地址、网络接口的状态
-
- ip route #展示系统的路由表。路由表是决定数据包在网络中如何转发
-
-
- 删除 ------------------------------------------------------------------------------
-
- #将容器从指定网络断开
- docker network disconnect my_network my_container
-
- #删除网络(无容器连接时才可删除)
- docker network rm my_network -f (-f表示强制删除)
-
-
- #删除容器
- docker rm 容器名/ID #(正在运行容器不能删除,除非加-f选项)
-
-
- 进入和退出容器 ------------------------------------------------------------------------
-
- #进入容器前要先启动
- docker start 容器名/ID #启动容器 无法启动时检查/etc/docker/daemon.json文件
- docker restart 容器名/ID #重启容器
- docker stop 容器名/ID #停止正在运行的容器
-
- # 进入容器,推荐exec 进入容器前要先启动容器
- docker attach 容器名/ID #使用attach进入后退出,容器停止运行
- docker exec -it 容器名/ID /bin/bash #使用exec进入后退出,容器不会停止
- docker exec -it 容器名/ID bash
-
- # 退出容器
- exit #直接退出
- crlt + P 再按 ctrl + Q #退出容器但是不终止运行
-
-
- docker相关服务 ------------------------------------------------------------------------
- systemctl start docker #启动服务
- systemctl status docker #查看状态 active(runing)表示已启动
- systemctl stop docker #停止服务
-
- ubuntu防火墙 ---------------------------------------------------------------------------
- sudo ufw status #查看防火墙状态,inactive是关闭,active是开启
- sudo ufw enable #开启防火墙
- udo ufw disable #关闭防火墙
-
创建容器时必须选择连接一个网络,如果不选择就是默认桥接模式brideg,可以使用docker network ls查看目前存在的网络。
- sudo docker network create \
- --driver macvlan \
- --subnet=<你的宿主机子网,如192.168.0.0/24> \
- --gateway=<你的宿主机网关> \
- -o parent=物理接口名称,如ens33 \
- net-1
参数介绍:
- --driver macvlan:指定网络类型为macvlan。
- --subnet:
192.168.1.0/24表示容器将会从这个子网范围内分配IP地址- --gateway: 通过宿主机网关容器知道如何路由到外部网络
- -o parent: 指定macvlan网络将绑定到宿主机的哪个物理网络接口
- net-1: 这个是你创建的网络名称
docker network ls #显示所有网络,如net-1
ip addr #查看所有网络接口的详细信息 ifconfig也可以
查询信息如下列所示:
我的物理网络接口为ens33,所以接口的IP地址配置显示为192.168.1.100/24。这里的/24就是子网掩码的CIDR表示形式,意味着网络部分有24个二进制的1,即子网掩码为255.255.255.0。因此,从这个输出中可以看出,该接口配置在一个子网为192.168.1.0/24的网络中,一般来说默认网关就是你的ip地址,比如这里的192.168.1.100。如果不确定则按下面步骤查询。
- 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
- inet 127.0.0.1/8 scope host lo
- valid_lft forever preferred_lft forever
- 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
- inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic ens33
- valid_lft 3444sec preferred_lft 3444sec
ip route #查看路由表,网关,其中包括了目标网络、网关、接口、标志以及路由的优先级等信息。路由表来决定数据包应当通过哪个接口(网络接口卡,如 Ethernet 卡)以及下一跳的IP地址(通常是网关)来转发数据。
default via [网关IP] dev [网络接口名称] proto [协议] metric [数值]
- sudo docker run -itd \
- --name container-1 \
- --network=net-1 \
- --ip=192.168.0.61 \
- -v /home/norten/Public/tools:/mnt \
- ubuntu
参数介绍:
- -i: 表示以交互模式运行容器,即使没有连接到终端也会保持STDIN(标准输入)打开
- -t: 为容器分配一个伪TTY(虚拟终端),这使得它看起来更像是一个交互式会话
- -d: 表示以后台模式运行容器(守护进程模式),你不会直接看到容器的输出,但容器会在后台持续运行
- --name container-1: 为新创建的容器指定一个名称
- --network=net-1: 指定容器要加入的网络名为
net-1- --ip=192.168.0.61: 为容器指定了一个固定的IP地址
- -v /home/norten/Public/tools:/mnt: 使用卷挂载功能,将宿主机的
/home/norten/Public/tools目录挂载到容器内的/mnt目录,mnt全称为mount挂载- ubuntu: 这是告诉Docker使用
ubuntu镜像作为基础来创建容器
需要注意的是:
docker inspect container-1
Mounts: (对应mnt)

Networks:

同样的,我们可以使用 docker inspect net-1 来查看这个网络上所连接的容器
(这里展示的是部分容器连接)

上面我们是使用了ssh终端(MobaXterm)来实现与ubuntu宿主机的交互,在宿主机上使用卷挂载来实现宿主机与容器之间的交互。还有一种方式可以实现windows电脑与ubuntu宿主机之间共享文件,具体看:
除此以外,容器在创建的时候还可以指定DNS,先查询宿主机的DNS,再指定容器的DNS,则能够让容器与宿主机DNS一致,是否需要看个人用途,这个不作过多介绍
sudo docker run -itd \ --name container-5 \ --network=my-macvlan-1 \ --ip=192.168.0.65 \ -v /home/norten/Desktop/SmbShare:/home/public/tools/MediumBoxBase \ --dns 宿主机DNS \ --dns 8.8.8.8 \ --dns 114.114.114.114 \ --dns-opt="ndots:0" \ --dns-opt="edns0" \ ubuntu
进入容器后直接使用脚本:./mnt/container_run_medium.sh
container_run_medium.sh内的脚本内容:
- rm -f *.log
- rm -f nohup.out
- rm -f cssd.dat
- nohup /mnt/simutools/pwbox_simu /mnt/simutools/pw_box.conf &
- /mnt/mediumSimu/MediumBoxBase /mnt/mediumSimu/hynn_flash_config_simu.conf
cat /etc/hostname docker inspect --format '{{.Name}}' 容器ID 脚本docker_operations.sh:
- #!/bin/bash
-
- # all definition
- NETWORK_NAME="net-1"
- VOLUME_MOUNT="-v /home/norten/Public/tools:/mnt"
- IMAGE_NAME="ubuntu"
-
- # View help command
- function help_container() {
- echo "/mnt/simutools# ./pwbox_simu pw_box.conf "
- echo "/mnt/mediumSimu# ./MediumBoxBase hynn_flash_config_simu.conf "
- echo " "
- echo " "
- echo "create: ./docker_operations.sh create [num]" #创建一个容器
- echo "./docker_operations.sh create 20 *means* create container-20 ,ip=192.168.0.80"
- echo " "
- echo " "
- echo "start: ./docker_operations.sh start [start_num] [end_num]" #启动容器
- echo "./docker_operations.sh start 20 25 *means* start 20-25 containers"
- echo "./docker_operations.sh start 20 *means* start one container"
- echo " "
- echo " "
- echo "exec: ./docker_operations.sh exec [num] " #进入容器
- echo "./docker_operations.sh exec 20 *means* execute container-20"
- echo "After you execute container ,you should use
to exit your container" - echo " "
- echo " "
- echo "stop: ./docker_operations.sh stop [start_num] [end_num]" #停止容器
- echo "./docker_operations.sh stop 20 25 *means* stop 20-25 containers"
- echo "./docker_operations.sh stop 20 *means* stop one container"
- echo " "
- echo " "
- echo "remove: ./docker_operations.sh remove [num] " #删除容器
- echo "./docker_operations.sh remove 20 *means* remove container-20"
- echo " "
- echo " "
- echo "info: ./docker_operations.sh info [container_ID] "
- echo " ./docker_operations.sh info a536fbad17b4 *means* view the container name" #进入容器后输入命令左边那一串就是容器的ID
- echo " "
- echo " "
- echo "
" #查看所有的容器 - echo "Used to see which containers are running"
- echo " "
- echo " "
- echo "
" #查看正在运行的容器 - echo "Used to see all containers exist"
- echo " "
- echo " "
- echo "
" - echo "Used to check all information about a container"
- echo " "
- echo " "
-
- }
-
- # Dynamic container creation
- function create_container() {
- echo "create zero paremeter is: $0"
- echo "create first paremeter is: $1"
- echo "create second paremeter is: $2"
-
- local num="$1"
- local CONTAINER_IP="192.168.0.$((num+60))"
- echo "IP IS $CONTAINER_IP"
- local CONTAINER_NAME="container-$num"
-
- # Check whether the IP address is already in use
- local existing_ips=($(docker inspect --format='{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq) 2>/dev/null))
- for ip in "${existing_ips[@]}"; do
- if [[ "$ip" == "$CONTAINER_IP" ]]; then
- echo "Error: IP Address $CONTAINER_IP is already in use by another container."
- exit 1
- fi
- done
-
- # Trying to create a container
- docker run -itd \
- --name "$CONTAINER_NAME" \
- --network="$NETWORK_NAME" \
- --ip="$CONTAINER_IP" \
- $VOLUME_MOUNT \
- $IMAGE_NAME \
- && echo "Container $CONTAINER_NAME created with IP $CONTAINER_IP." \
- || { echo "Failed to create container $CONTAINER_NAME."; exit 1; }
-
- }
-
-
- # Start specified or a range of containers
- function start_container() {
- echo "start zero paremeter is: $0"
- echo "start first paremeter is: $1"
- echo "start second paremeter is: $2"
-
- local start_num="$1"
- local end_num="${2:-$start_num}" # If the second argument is not provided, it defaults to the value of the first argument
-
- for (( i=start_num; i<=end_num; i++ )); do
- local CONTAINER_NAME="container-$i"
- if docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME\$"; then
- echo "Starting container $CONTAINER_NAME..."
- docker start "$CONTAINER_NAME"
- echo "Container $CONTAINER_NAME started."
- else
- echo "Error: Container $CONTAINER_NAME does not exist."
- exit 1
- fi
- done
- }
-
-
- # Stop specified or a range of containers
- function stop_container() {
- local start_num="$1"
- local end_num="${2:-$start_num}" # If the second argument is not provided, it defaults to the value of the first argument
-
- for (( i=start_num; i<=end_num; i++ )); do
- local CONTAINER_NAME="container-$i"
- if docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME\$"; then
- echo "Stopping container $CONTAINER_NAME..."
- docker stop "$CONTAINER_NAME"
- echo "Container $CONTAINER_NAME stopped."
- else
- echo "Warning: Container $CONTAINER_NAME does not exist."
- fi
- done
- }
-
- # Enter the shell of a specified container
- function exec_container() {
- local container_num="$1"
- local CONTAINER_NAME="container-$container_num"
-
- if docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME\$"; then
- echo "Entering container $CONTAINER_NAME..."
- docker exec -it "$CONTAINER_NAME" bash
- else
- echo "Error: Container $CONTAINER_NAME does not exist or is not running."
- exit 1
- fi
- }
-
-
- # Remove a specified container
- function remove_container() {
- local container_num="$1"
- local CONTAINER_NAME="container-$container_num"
-
- if docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME\$"; then
- echo "Removing container $CONTAINER_NAME..."
- docker rm -f "$CONTAINER_NAME"
- echo "Container $CONTAINER_NAME removed."
- else
- echo "Error: Container $CONTAINER_NAME does not exist."
- exit 1
- fi
- }
-
-
- # 添加一个新的函数来查询容器信息
- function info_container() {
- local search_term="$1"
- local containers_info=$(docker ps -a --format '{{.ID}} {{.Names}}' | grep "$search_term")
-
- if [ -z "$containers_info" ]; then
- echo "No container found matching '$search_term'."
- return 1
- fi
-
- echo "Matching containers:"
- echo "$containers_info" | while read -r container_id container_name; do
- echo "ID: $container_id, Name: $container_name"
- done
- }
-
-
- case "$1" in
- help)
- help_container
- ;;
-
- create)
- if [ "$#" -ne 2 ]; then
- echo "Error: You should provide a parameter after 'create'."
- exit 1
- fi
-
- if ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; then
- echo "Error: The number must be an integer between 1 and 1000."
- exit 1
- fi
-
- create_container "$2"
- ;;
-
- start)
- # Check the number of parameters to determine whether to start a single container or a container range
- if [ "$#" -lt 2 ]; then
- echo "Error: You should provide at least one number after 'start'."
- exit 1
- elif [ "$#" -eq 2 ]; then
- # If there are only two parameters, try starting a container
- start_container "$2"
- elif [ "$#" -eq 3 ]; then
- # If you have three parameters, try starting a series of containers
- if ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]] || ! [[ "$3" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; then
- echo "Error: Both numbers must be integers between 1 and 1000."
- exit 1
- fi
- if [ "$2" -gt "$3" ]; then
- echo "Error: The first number must be less than or equal to the second."
- exit 1
- fi
- start_container "$2" "$3"
- else
- echo "Error: Too many arguments for 'start'."
- exit 1
- fi
- ;;
-
- stop)
- if [ "$#" -lt 2 ]; then
- echo "Error: You should provide at least one number after 'stop'."
- exit 1
- fi
-
- if ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; then
- echo "Error: The number(s) must be integers between 1 and 1000."
- exit 1
- fi
-
- if [ "$#" -eq 2 ]; then
- stop_container "$2"
- elif [ "$#" -eq 3 ]; then
- if ! [[ "$3" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; then
- echo "Error: Both numbers must be integers between 1 and 1000."
- exit 1
- fi
- if [ "$2" -gt "$3" ]; then
- echo "Error: The second number must be greater than or equal to the first."
- exit 1
- fi
- stop_container "$2" "$3"
- else
- echo "Error: Too many arguments for 'stop'."
- exit 1
- fi
- ;;
-
- exec)
- if [ "$#" -ne 2 ]; then
- echo "Error: You should provide exactly one number after 'exec'."
- exit 1
- fi
-
- if ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; then
- echo "Error: The number must be an integer between 1 and 1000."
- exit 1
- fi
-
- exec_container "$2"
- ;;
-
- remove)
- if [ "$#" -ne 2 ]; then
- echo "Error: You should provide exactly one number after 'remove'."
- exit 1
- fi
-
- if ! [[ "$2" =~ ^[1-9][0-9]{0,2}|[1-9][0-9]{3}$ ]]; then
- echo "Error: The number must be an integer between 1 and 1000."
- exit 1
- fi
-
- remove_container "$2"
- ;;
- info)
- if [ "$#" -ne 2 ]; then
- echo "Usage: $0 info
" - exit 1
- fi
- info_container "$2"
- ;;
-
- logs|status)
- echo "Function '$1' has not been updated to handle numbered containers."
- exit 1
- ;;
- *)
- echo "Invalid command. Use './docker_operations.sh help' to get instructions."
- exit 1
- ;;
- esac
-
- exit 0
- vi [name].sh #编写
- more [name].sh #查看信息
- chmod +x [name].sh #添加权限
-
- fuser -n file xxx.sh #查找占用进程
- kill Process_ID