banner
Hi my new friend!

docker学习

Scroll down

docker 配置代理

使用v2raya来代理: 安装 - v2rayA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建 Docker 代理配置文件
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=socks5://127.0.0.1:20170"
Environment="HTTPS_PROXY=socks5://127.0.0.1:20170"
EOF

# 重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker

# 测试拉取镜像(不再需要 proxychains)
docker pull praqma/network-multitool

image-20250520211246977

docker镜像构建

创建一个镜像

首先新建一个node.js项目,这样就会自动生成package.json文件

1
npm init -y

image-20250528105612663

由于构建服务器需要express框架,所以就直接进行安装express框架

1
npm install express

此时package.json中的依赖就会出现express的键值对,并且伴随着node_modules出现,这个文件夹会保存安装的模块

image-20250528111041838

接下来创建app.js文件

1
2
3
4
5
6
7
8
9
const express = require("express");
const app = express();
const PORT = 3000;

app.get("/",(req,res) =>{
res.send("<p>蛋家好啊</p>")
})

app.listen(PORT, () => console.log("端口3000走起!"));

可以成功运行

image-20250528112229155

接下来就是正式开始制作Dockerfile

1
2
3
4
5
6
7
FROM node:18-alpine3.15
WORKDIR /egg # 指定工作目录(不是必须)
COPY package.json . #这个"."是工作路径的相对路径
RUN npm install # 这个就会按照package.json来进行安装
COPY . . # 把本地的所有文件都复制到工作路径 docker中使用缓存package.json不会被复制两次,前面复制了就不会再次复制,而json有缓存,就不用重新去安装依赖,提高速度
EXPOSE 3000 # 暴露端口号
CMD ["node", "app.js"]

新建一个.dockerignore可以把不想在COPY . .步骤中复制进去的文件填写到里面

1
2
3
4
5
node_modules
Dockerfile
.dockerignore
.git
.gitignore

然后构建镜像

1
docker build .

使用命令查看镜像列表

1
sudo docker images

image-20250528114915895

使用sudo docker tag 镜像ID 名字来添加名字和标签(一次性添加),如果没有后边的”:”的内容就是lastest版本号

image-20250528115159166

docker login登录到docker hub账号,然后就可以把新建好的镜像推送到docker hub了

1
docker push dansoncut/node.js:v1.0

在构建镜像的时候就自定义名字:

1
docker build -t eggpain-image .

image-20250528132240693

删除镜像,如果有些镜像再被使用就需要使用-f强行删除(注意还是需要加上版本号,不然默认是lastest可能找不到)

1
docker rmi -f dansoncut/node.js:v1.0

image-20250528132659748

然后使用这个镜像来运行一个容器,如果成功会返回ID号,使用-d来设置后台运行image-20250528132850660

但是发现虽然暴露了3000端口但是这是在容器中的,并没有暴露到宿主机中,宿主机中访问3000端口没有任何服务

image-20250528133456736

这是因为Dockerfile文件中的EXPOSE只是让人知道这个镜像在用容器的某个端口,和宿主机无关,所以需要在启动端口的时候手动进行端口映射(主机端口:容器端口) 还可以在后面自定义名字(–name nishixiaozhu)

1
sudo docker run -d -p 3000:3000 --name nishixiaozhu eggpain-image

image-20250528134152450

image-20250528134449846

删除一个容器

1
2
sudo docker rm 部分id/容器名称
sudo docker rm -f 部分id/容器名称 # 强行删除

停止容器,会给容器时间来慢慢关闭

1
docker stop -t=60 容器ID或容器名

但是发现当在本地修改js文件的时候,镜像及正在运行的容器是不会改变的,这个时候就需要进行一个地址的绑定,让他去指向目标地址(注意这里的-需要绝对路径/:/工作路径)

1
sudo docker run -d -v /home/ubuntu/Desktop/:/nodejstest -p 3000:3000 --name nicaishixiaozhu eggpain-image

但是出现了新的情况,如果直接修改的话原来的node_modules会被覆盖,所以需要指明不需要同步的文件夹,就是再用-v指定一个文件夹(不同步)

1
sudo docker run -d -v /home/ubuntu/Desktop/:/nodejstest -v /egg/node_modules -p 3000:3000 --name eggpain-conner eggpain-image

但是这样如果容器中出现了新的文件夹,宿主机上也会同步(可能会被上传恶意代码)所以需要设置本地为只读模式:ro(readonly)

1
sudo docker run -d -v /home/ubuntu/Desktop/:/nodejstest:ro -v /egg/node_modules -p 3000:3000 --name eggpain-conner eggpain-image

然后会发现设置到这里还是没有用,因为镜像已经构建了,还需要自动重启去更新镜像的内容

用于自动重启 Node.js 应用当文件发生变化时(比如修改了 .js 文件)

1
npm i nodemon --save-dev

image-20250528154341842

然后修改scripts

image-20250528154552032

然后再修改Dockerfile

1
CMD ["npm", "run", "dev"]

删除原来的image在重新搭建docker build -t eggpain-image

image-20250528155442820


搞不定不太想搞了现在(哭 存个档下次再搞)

docker-compose

启动单个容器的命令很长,如果要启动多个容器来执行协调不同的任务(mysql/nginx/apache)就需要一个统筹启动的应用,docker-compose就可以解决

需要创建一个docker-compose.yml文件

1
2
3
4
5
6
7
8
9
version: "3.8"
services:
eggpain-container:
build: .
ports:
- "3000:3000"
volumes:
- ./:/egg:ro
- /egg/node_modules

然后执行

1
docker-compose up -d --build

image-20250528190423507

image-20250528190457409

可以发现docker-compose创建了新的镜像(nodejstest_eggpain-container_1)和新的容器(nodejstest_eggpain-container)

清除容器

1
2
sudo docker-compose down -v
# 使用 -v 选项会删除所有与容器关联的卷,这意味着所有存储在卷中的数据将被永久删除

docker网络

【入门篇】Docker网络模式Linux - Bridge | Host | None_哔哩哔哩_bilibili

Bridge 网络

在安装docker之前的linux网卡信息是这样的,只有一张以太网网卡(ens33)和一张lo(loopback回环,只能和自己联通)

image-20250520105201812

docker安装命令:

1
sudo apt-get insatll docker.io -y | less

会发现此时多了一个docker的网卡信息:

image-20250520110133547

查看这张网卡的具体信息如下:

1
sudo docker network inspect bridge | less

image-20250520112501883

使用jq来提取一些当前有用的信息:

1
sudo docker network inspect bridge | jq '.[0] | {Name:.Name, Id:.Id, Driver:.Driver, IPAM:.IPAM.Config, Containers:.Containers, Options:.Options}'

得到以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ubuntu@ubuntu:~/Desktop$ sudo docker network inspect bridge | jq '.[0] | {Name:.Name, Id:.Id, Driver:.Driver, IPAM:.IPAM.Config, Containers:.Containers, Options:.Options}'
{
"Name": "bridge",
"Id": "cf904d02cf0101bdf9135a9b7be444ed323fdf5f32a3a98fe7000374d5062347",
"Driver": "bridge",
"IPAM": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
],
"Containers": {},
"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"
}
}

image-20250520114033429

此时可以看到Containers中还没有任何容器,可以添加一个功能性容器然后再来看看实力,如果本地没有这个镜像也会自动拉取

1
sudo docker run -d --name egg1 --hostname egg1 praqma/network-multitool

image-20250520211717949

然后可以使用以下命令查看容器是否正在运行

1
sudo docker ps

image-20250520211902588

然后再次使用命令查看网卡信息就会发现多了一个容器了

image-20250520212210365

此时查看接口信息会发现多了一个奇怪的接口名称,实际上这就是使用bright的网卡情况,而且对于网卡的排序也出了问题,发现顺序为4的网卡消失了

弹幕: veth虚拟以太网接口生成了一对vethx和vethy,vethx在宿主机中与虚拟网卡docker0虚拟桥接网卡相连,vethy在容器网络命名空间内,这样实现容器进程与容器之外的外部网络通信

1
2
# 需要注意的是,这个地方查看网卡信息必须使用以下命令,使用ifconfig无法查看从属关系
ip address

image-20250520212920531

使用以下命令按json格式化网卡信息,并且输出

1
ip -json address show dev vethd6a5d21 | jq .

image-20250520213238874

进入容器查看容器内的网卡信息

1
sudo docker exec -it egg1 bash

可以清晰的发现丢失的网卡4就在这里!

image-20250520214407274

使用命令查询这张网卡的具体信息

1
ip -json -detail address show dev eth0 | jq '.[0] | {ifindex:.ifindex, link_index:.link_index, ifname:.ifname, linkinfo:.linkinfo , addr_info:.addr_info}'

image-20250520215115314

可以发现对于linkinfo这个参数,就可以判断出当前接口正在和哪个接口进行连接

同样的命令查询以太网网卡是会显示null

image-20250520215356728

如果重新添加一个容器,也会发现这个容器有一张在宿主机中隐藏的虚拟网卡,而且这张网卡也是连接到veth上的,然后在宿主机的网卡信息中也会发现一张指向虚拟机的虚拟网卡,也就是这个情况

image-20250520215829355

image-20250520221709111

Bridge型

使用命令来查看现在的网络列表

1
sudo docker network ls

image-20250527170915929

创建bridge网络

1
2
3
# -d使用bridge驱动来创建
# naihe-bridge 自定义网络名称
sudo docker network create -d bridge naihe-bridge

image-20250527190208629

通过查询docker network inspect可以发现实际上两个网络的网段是不一样的

1
sudo docker network inspect 网络名称 | jq '.[0] | {Name:.Name, Id:.Id, Driver:.Driver, IPAM:.IPAM.Config, Containers:.Containers}'

image-20250527191452009

使用命令ip address查看网卡信息发现出现了一张新的网卡并且这个网卡名称和网卡id是一样的
image-20250527191809962

现在来创建一个新容器指定使用这个网卡如下

1
sudo docker run -d --name naihe1 --hostname naihe1 --network naihe-bridge praqma/network-multitool

然后查看网卡信息ip address可以发现创建了一个新的网卡使用的master网卡就是之前创建的br-9a14e1ce05d3

image-20250527192335545

可以发现网卡下出现了两个容器

image-20250527192906422

使用命令进去docker中的bash来ping另一个容器的ip发现是可以ping通的

1
sudo docker exec -it naihe1 bash

image-20250527193211984

而且实际上自定义网卡还自动配置了DNS可以直接ping主机名来实现通信,但是实际上这里指定了hostname所以不明显
image-20250527193311626

再创建一个容器但是不指定hostname再尝试ping看看能不能ping通

1
sudo docker run -d --name naihe3 --network naihe-bridge praqma/network-multitool

虚拟机死机了,重启一个停止的容器命令如下:

1
2
3
4
5
# 查看所有容器信息
sudo docker ps -a

# 启动一个停止的容器
sudo docker start naihe1

可以发现在没有指定容器名的前提下使用自定义网卡是可以实现自动配置dns的

image-20250527195439098

删除创建的网络,但是默认的网络是没有办法删除的

1
docker network rm naihe-bridge

host网络型

bridge型的网络(无论是自定义还是默认)都需要手动暴露端口才能实现,使用host网络就可以避免这个问题


host网络无法自定义创建,只能有一个,会报错

1
sudo docker network create -d host newhost

image-20250527200827615

查看网络环境发现是没有ip的

1
docker network inspect host | jq '.[0] | {Name:.Name, Id:.Id, Driver:.Driver, IPAM:.IPAM.Config, Containers:.Containers, Options:.Options}'

image-20250527211749074

如果是指定端口关联,host模式下会出问题,因为host模式是不需要端口关联的

1
sudo docker run --name egg --network host -p 8080:80 -d praqma/network-multitool

发现出现警告但是仍然可以创建新的容器

image-20250527214116672image-20250527214201495

实际上这个host网络下的容器就直接是宿主的一个应用了(只有linux下是这样的),在容器中与宿主设备中查看ip address得到的网络信息是一样的

None就是不允许进行网络通信

区别

image-20250527214551605

其他文章
cover
安装windwos到移动硬盘
  • 25/05/28
  • 23:19
  • 零碎学习
cover
vpn协议了解
  • 25/05/13
  • 10:00
  • 协议学习
目录导航 置顶
  1. 1. docker 配置代理
  2. 2. docker镜像构建
    1. 2.1. 创建一个镜像
  3. 3. docker-compose
  4. 4. docker网络
    1. 4.1. Bridge 网络
    2. 4.2. Bridge型
    3. 4.3. host网络型
    4. 4.4. None就是不允许进行网络通信
    5. 4.5. 区别
请输入关键词进行搜索