docker就是用来把某人的程序完好运行在另一个人电脑上的小虚拟机

YSir
2025.10.28
以下内容只涉及Windows+WSL

参考:https://github.com/tech-shrimp/docker_installer.git

环境

  1. 打开virtual machine platform适用于Linux的Windows子系统两个功能
  2. 运行俩命令
    1
    2
    wsl --set-default-version 2     //要求默认版本为wsl2
    wsl --update --web-download //安装wsl
  3. 下docker desktop https://www.docker.com/products/docker-desktop/

命令

  1. docker pull [<仓库地址>docker.io]/[<命名空间(作者名)>library]/niginx:[<版本号>latest],如果全部简化则为官方镜像docker pull niginx,一个镜像库由仓库地址+命名空间+镜像名组成

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    C:\Users\YSir>docker pull nginx         //linux系统需要加sudo
    Using default tag: latest
    latest: Pulling from library/nginx
    38513bd72563: Pull complete
    a0a6ab141558: Pull complete
    0e86847a3920: Pull complete
    1bace2083289: Pull complete
    89df300a082a: Pull complete
    35fb9ffa6621: Pull complete
    5545b08f9d26: Pull complete
    Digest: sha256:f547e3d0d5d02f7009737b284abc87d808e4252b42dceea361811e9fc606287f
    Status: Downloaded newer image for nginx:latest
    docker.io/library/nginx:latest
  2. 配置镜像站(下载有问题),复制:

    1
    2
    3
    4
    5
    6
    "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://docker.1panel.live",
    "https://hub.rat.dev"
    ]

    粘贴到此处:点击apply&restart

  3. docker images查看已下载的镜像

  4. docker rmi <镜像名或ID>删除已下载的镜像(i代表images),docker rm即删除正在运行的容器,加-f可强制删除

  5. docker run <镜像名> [-d] [-p <本机端口>:<容器端口>] [-v <本机目录:容器目录>]运行容器

    1. -d可以防止刷屏,容器放后台(实际上如果不pull直接run也可以,docker将自动pull)
    2. -p端口映射,将容器与本机互通
      例如
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      C:\Users\YSir>docker run -p 80:80 nginx
      /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
      /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
      10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
      10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
      /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
      /docker-entrypoint.sh: Configuration complete; ready for start up
      2025/10/31 13:45:04 [notice] 1#1: using the "epoll" event method
      2025/10/31 13:45:04 [notice] 1#1: nginx/1.29.3
      2025/10/31 13:45:04 [notice] 1#1: built by gcc 14.2.0 (Debian 14.2.0-19)
      2025/10/31 13:45:04 [notice] 1#1: OS: Linux 5.15.167.4-microsoft-standard-WSL2
      2025/10/31 13:45:04 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
      2025/10/31 13:45:04 [notice] 1#1: start worker processes
      2025/10/31 13:45:04 [notice] 1#1: start worker process 29
      2025/10/31 13:45:04 [notice] 1#1: start worker process 30
      ...
      此时我访问localhost:80就会出现nginx的欢迎界面,ctrl+c以结束
    3. -v设置挂载卷,设置后使得容器文件夹使用本机文件夹,但只能访问本机文件夹(注:有一个历史遗留问题,Linux目录路径为/而Windows为\)
      例子
      1
      2
      C:\Users\YSir>docker run -p 80:80 -v C:\website\html:/usr/share/nginx/html nginx
      //一定要在C:\website\html中也创建一个index.html,否则403
      还可以使用命名卷挂载
      • 创建挂载卷docker volume create <挂载卷名>
      • 查看挂载卷位置docker volume inspect <挂载卷名>
      • 命名卷会自动复制第一次使用时会自动拷贝容器内对应文件
      • docker volume list可例出所有使用中的命名卷
      • docker volume rm <命名卷名>删除命名卷
      • docekr volume prune -a删除所有未在使用的命名卷
      • 这玩意在Windows里有小bug,先不管
    4. -e设置环境变量
      1
      2
      3
      4
      5
      docker run -d \
      -p 27017:27017 \
      -e MONGO_INITDB_ROOT_USERNAME = tech \
      -e MONGO_INITDB_ROOT_PASSWORD = shrimp \
      mongo
      这样数据库的账号密码就会作为环境变量传递进去,使mongo数据库预设好账号密码。
      使用mongosh "mongodb://tech:shrimp@111.231.100.92:27017"即可连入数据库(111.231.100.92是别人的服务器),不清楚环境变量可以在镜像文档里找
    5. --name <容器名>为容器自定义名称以取代容器ID,这样就可以直接用docker rm <容器名>来删除容器
    6. -t可进入容器,常搭配--rm使用
    7. --rm当容器停止运行时删除容器
      docker run -t --rm alpine(alpine是一个轻型linux),这样可以直接进入容器内部,并在退出容器的同时删除容器,用于临时调试容器与之相同的还有--restart
      docker run --restart always nginx如果容器被关闭就会立即重启
      docker run --restart unless-stopped如果是非手动停止容器就立即重启
    8. start启动容器
    9. stop停止容器,使用start和stop可以让docker将容器数据保留下来,避免被删除
  6. docker ps查看正在运行的容器(镜像可比作类,而容器就是对象)-a可查看所有容器

  7. docker stop <容器ID>停止某运行中的容器,以方便删除容器

  8. docker container prune可以直接删掉停止使用的容器

  9. docker inspect <容器ID>查看容器详细信息,可查看启动参数,内容可能看不懂,丢给ai就好

  10. docker create <镜像名>run差不多,唯一区别就是需要手动start

  11. docker log <容器ID>查看容器日志-f可实时刷新

调试

dockerlinuxcgroupsnamespaces实现容器化,cgroups用来限制容器资源调度上限,namespaces用来隔离容器使容器看不见外部情况

  1. docker exec <容器ID> <linux命令>在容器内部执行Linux命令,如docker exec d123d123 ps -ef查看容器d123d123的进程,还有常用命令docker exec -it <容器ID> /bin/sh进入一个容器内部获得其shell,当然容器简单到连文本编辑工具vi都没有,要自己安装
  2. 进入容器内部后使用cat /etc/os-release可查看容器所使用的linux系统,依照系统下载文本编辑器等工具,以nginx举例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    docker exec -it <容器ID> /bin/sh        //进入容器
    # cat /etc/os-release
    PRETTY_NAME="Debian GNU/Linux 13 (trixie)" //这里可发现使用的是Debian
    ...
    # apt update //debain使用apt命令安装软件,更新apt索引
    # apt install vim //安装文本编辑器vim
    # cd /usr/share/nginx/html //进入网页默认文件夹
    # cat index.html //编辑默认网页

制作镜像并推送到dockerhub

感觉对我没啥用,下次再说 :)

Docker网络设置

bridge桥接模式

默认birdge桥接模式,所有容器默认连接到容器内网,所有容器分配一个IP地址(大多172.17.x.x),并且容器内网与本机网络隔离,
docker network create network1可创建子网,仍属于桥接模式,可指定容器加入子网,不同子网的容器不可相互通信,同一子网的好处是可以直接使用容器名访问而非IP
例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//该容器没进行端口映射,目的是不能让客户机直接访问数据库
root@LAPTOP-L57F2HR5:/# docker run -d \
> --name my_mongodb \ //为容器命名,使得同一子网的容器可以直接找到该容器不需要知道IP
> -e MONGO_INITDB_ROOT_USERNAME=tech \ //设置环境变量
> -e MONGO_INITDB_ROOT_PASSWORD=shrimp \
> --network network1 \ //接入子网network1
> mongo
0787c32666073e64489e84d67fcec037ebd70de00c514a3aa1d17b41e6f08555

//启动了一个mongodb的客户端,这才是希望客户机看到的,所以设置了端口映射
root@LAPTOP-L57F2HR5:/# docker run -d \
> --name my_mongodb_express \
> -p 8081:8081 \
//这里并没有写my_mongodb的IP而是直接告诉他名字,因为容器子网内部有一个DNS
> -e ME_CONFIG_MONGODB_SERVER=my_mongodb \
> -e ME_CONFIG_MONGODB_ADMINUSERNAME=tech \
> -e ME_CONFIG_MONGODB_ADMINPASSWORD=shrimp \
> --network network1 \
> mongo-express

这样一来就可以在浏览器里访问该数据库了
默认用户名为admin,密码为pass

接下来进入mongodb-express里看看是怎么个事

1
2
3
4
5
6
root@LAPTOP-L57F2HR5:/# docker exec -it my_mongodb_express /bin/sh
/app # ping my_mongodb //这里ping的是容器名
PING my_mongodb (172.18.0.2): 56 data bytes //而这里自动转为IP地址,所以容器子网里有DNS
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.153 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.148 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.095 ms

子网逻辑图

Host模式

该模式容器直接共享本机网络,使用本机IP,无需-p进行端口映射
docker run --network host <容器名>以设置Host模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@LAPTOP-L57F2HR5:/# docker run -d --network host nginx      //此时直接访问localhost:80可访问
root@LAPTOP-L57F2HR5:/# docker exec -it 777a5aed9007 /bin/sh //进入容器看看IP
# apt update
# apt install iproute2 //想查看IP先安装这个工具
# ip addr show
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
inet6 ::1/128 scope host proto kernel_lo
valid_lft forever preferred_lft forever
2: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether b6:6a:6d:f5:3d:09 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 //看这里的IP,有bug:(,先不管,反正应该相同就对了:)
valid_lft forever preferred_lft forever

网络命令

docker network list列出已有网络(包括已创建子网)

1
2
3
4
5
NETWORK ID     NAME       DRIVER    SCOPE
b4d69f5d9f25 bridge bridge local //系统自带
5f5d36bcccdd host host local //系统自带
af2dd9a83849 network1 bridge local
ca033ed54219 none null local //系统自带

docker network rm <网络名>删除已有网络(系统自带无法删除)