docker 配置代理
使用v2raya来代理: 安装 - v2rayA
1 | # 创建 Docker 代理配置文件 |
docker镜像构建
创建一个镜像
首先新建一个node.js
项目,这样就会自动生成package.json
文件
1 | npm init -y |
由于构建服务器需要express框架,所以就直接进行安装express框架
1 | npm install express |
此时package.json
中的依赖就会出现express的键值对,并且伴随着node_modules出现,这个文件夹会保存安装的模块
接下来创建app.js
文件
1 | const express = require("express"); |
可以成功运行
接下来就是正式开始制作Dockerfile
1 | FROM node:18-alpine3.15 |
新建一个.dockerignore
可以把不想在COPY . .
步骤中复制进去的文件填写到里面
1 | node_modules |
然后构建镜像
1 | docker build . |
使用命令查看镜像列表
1 | sudo docker images |
使用sudo docker tag 镜像ID 名字
来添加名字和标签(一次性添加),如果没有后边的”:”的内容就是lastest版本号
docker login登录到docker hub账号,然后就可以把新建好的镜像推送到docker hub了
1 | docker push dansoncut/node.js:v1.0 |
在构建镜像的时候就自定义名字:
1 | docker build -t eggpain-image . |
删除镜像,如果有些镜像再被使用就需要使用-f
强行删除(注意还是需要加上版本号,不然默认是lastest可能找不到)
1 | docker rmi -f dansoncut/node.js:v1.0 |
然后使用这个镜像来运行一个容器,如果成功会返回ID号,使用-d
来设置后台运行
但是发现虽然暴露了3000端口但是这是在容器中的,并没有暴露到宿主机中,宿主机中访问3000端口没有任何服务
这是因为Dockerfile
文件中的EXPOSE
只是让人知道这个镜像在用容器的某个端口,和宿主机无关,所以需要在启动端口的时候手动进行端口映射(主机端口:容器端口) 还可以在后面自定义名字(–name nishixiaozhu)
1 | sudo docker run -d -p 3000:3000 --name nishixiaozhu eggpain-image |
删除一个容器
1 | sudo docker rm 部分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 |
然后修改scripts
然后再修改Dockerfile
1 | CMD ["npm", "run", "dev"] |
删除原来的image在重新搭建docker build -t eggpain-image
搞不定不太想搞了现在(哭 存个档下次再搞)
docker-compose
启动单个容器的命令很长,如果要启动多个容器来执行协调不同的任务(mysql/nginx/apache)就需要一个统筹启动的应用,docker-compose就可以解决
需要创建一个docker-compose.yml
文件
1 | version: "3.8" |
然后执行
1 | docker-compose up -d --build |
可以发现docker-compose创建了新的镜像(nodejstest_eggpain-container_1
)和新的容器(nodejstest_eggpain-container
)
清除容器
1 | sudo docker-compose down -v |
docker网络
Bridge 网络
在安装docker之前的linux网卡信息是这样的,只有一张以太网网卡(ens33)和一张lo(loopback回环,只能和自己联通)
docker安装命令:
1 | sudo apt-get insatll docker.io -y | less |
会发现此时多了一个docker的网卡信息:
查看这张网卡的具体信息如下:
1 | sudo docker network inspect bridge | less |
使用jq来提取一些当前有用的信息:
1 | sudo docker network inspect bridge | jq '.[0] | {Name:.Name, Id:.Id, Driver:.Driver, IPAM:.IPAM.Config, Containers:.Containers, Options:.Options}' |
得到以下内容
1 | ubuntu@ubuntu:~/Desktop$ sudo docker network inspect bridge | jq '.[0] | {Name:.Name, Id:.Id, Driver:.Driver, IPAM:.IPAM.Config, Containers:.Containers, Options:.Options}' |
此时可以看到Containers
中还没有任何容器,可以添加一个功能性容器然后再来看看实力,如果本地没有这个镜像也会自动拉取
1 | sudo docker run -d --name egg1 --hostname egg1 praqma/network-multitool |
然后可以使用以下命令查看容器是否正在运行
1 | sudo docker ps |
然后再次使用命令查看网卡信息就会发现多了一个容器了
此时查看接口信息会发现多了一个奇怪的接口名称,实际上这就是使用bright的网卡情况,而且对于网卡的排序也出了问题,发现顺序为4的网卡消失了
弹幕: veth虚拟以太网接口生成了一对vethx和vethy,vethx在宿主机中与虚拟网卡docker0虚拟桥接网卡相连,vethy在容器网络命名空间内,这样实现容器进程与容器之外的外部网络通信
1 | # 需要注意的是,这个地方查看网卡信息必须使用以下命令,使用ifconfig无法查看从属关系 |
使用以下命令按json格式化网卡信息,并且输出
1 | ip -json address show dev vethd6a5d21 | jq . |
进入容器查看容器内的网卡信息
1 | sudo docker exec -it egg1 bash |
可以清晰的发现丢失的网卡4就在这里!
使用命令查询这张网卡的具体信息
1 | ip -json -detail address show dev eth0 | jq '.[0] | {ifindex:.ifindex, link_index:.link_index, ifname:.ifname, linkinfo:.linkinfo , addr_info:.addr_info}' |
可以发现对于linkinfo
这个参数,就可以判断出当前接口正在和哪个接口进行连接
同样的命令查询以太网网卡是会显示null
的
如果重新添加一个容器,也会发现这个容器有一张在宿主机中隐藏的虚拟网卡,而且这张网卡也是连接到veth
上的,然后在宿主机的网卡信息中也会发现一张指向虚拟机的虚拟网卡,也就是这个情况
Bridge型
使用命令来查看现在的网络列表
1 | sudo docker network ls |
创建bridge网络
1 | # -d使用bridge驱动来创建 |
通过查询docker network inspect
可以发现实际上两个网络的网段是不一样的
1 | sudo docker network inspect 网络名称 | jq '.[0] | {Name:.Name, Id:.Id, Driver:.Driver, IPAM:.IPAM.Config, Containers:.Containers}' |
使用命令ip address
查看网卡信息发现出现了一张新的网卡并且这个网卡名称和网卡id是一样的
现在来创建一个新容器指定使用这个网卡如下
1 | sudo docker run -d --name naihe1 --hostname naihe1 --network naihe-bridge praqma/network-multitool |
然后查看网卡信息ip address
可以发现创建了一个新的网卡使用的master网卡就是之前创建的br-9a14e1ce05d3
可以发现网卡下出现了两个容器
使用命令进去docker中的bash来ping另一个容器的ip发现是可以ping通的
1 | sudo docker exec -it naihe1 bash |
而且实际上自定义网卡还自动配置了DNS可以直接ping主机名来实现通信,但是实际上这里指定了hostname所以不明显
再创建一个容器但是不指定hostname再尝试ping看看能不能ping通
1 | sudo docker run -d --name naihe3 --network naihe-bridge praqma/network-multitool |
虚拟机死机了,重启一个停止的容器命令如下:
1 | # 查看所有容器信息 |
可以发现在没有指定容器名的前提下使用自定义网卡是可以实现自动配置dns的
删除创建的网络,但是默认的网络是没有办法删除的
1 | docker network rm naihe-bridge |
host网络型
bridge型的网络(无论是自定义还是默认)都需要手动暴露端口才能实现,使用host网络就可以避免这个问题
host网络无法自定义创建,只能有一个,会报错
1 | sudo docker network create -d host newhost |
查看网络环境发现是没有ip的
1 | docker network inspect host | jq '.[0] | {Name:.Name, Id:.Id, Driver:.Driver, IPAM:.IPAM.Config, Containers:.Containers, Options:.Options}' |
如果是指定端口关联,host模式下会出问题,因为host模式是不需要端口关联的
1 | sudo docker run --name egg --network host -p 8080:80 -d praqma/network-multitool |
发现出现警告但是仍然可以创建新的容器
实际上这个host网络下的容器就直接是宿主的一个应用了(只有linux下是这样的),在容器中与宿主设备中查看ip address
得到的网络信息是一样的