• 镜像是一种轻量级, 可执行的独立软件包, 用来打包软件运行环境和基于运行环境开发的软件; 它包含运行某个软件的所有东西(代码, 运行环境, 环境变量, 配置文件)
  • UnionFS(联合文件系统): UnionFS是一种分层, 轻量级并且高性能的文件系统; 它支持对文件系统的修改作为一次提交来一层层叠加, 同时可以将不同目录挂载到同一虚拟文件系统下; UnionFS是Docker镜像的基础; 镜像可以通过分层进行继承, 基于基础镜像, 可以制作各种应用镜像
  • docker镜像实际就是一层一层的文件系统组成, 这种层级的文件系统就是UnionFS
  • **BootFS**(boot file system): 主要包含bootloader和kernel, bootloader主要负责引导加载kernel(内核), linux在刚启动的时候会加载bootfs, 当bootfs加载完成之后, 整个内核就都在内存中了, 此时内存的使用权就有bootfs转交给了内核, 然后系统就会卸载掉bootfs;
  • **RootFS**(root file system) : rootfs就是不同操作系统的发行版本, 如ubuntu, centos; linux系统中的/dev, /proc, /bin, /etc等标准目录就是rootfs
  • docker中的镜像们统一使用公共的bootfs(bootfs非常大); 镜像中不包含bootfs的, 镜像主要有rootfs+应用组成, 所以比较小;
  • 对于精简的OS, rootfs是非常小的, 只需要包含最基本的命令, 工具和程序库就可以了, 因为底层使用了宿主机的内核, 精简OS只需提供rootfs即可; 不同的linux发行版本, bootfs基本是一致的, rootfs会有差异, 因为不同的linux发行版本可以使用公用的bootfs
  • 镜像秒级启动的原因: 不许用使用bootloader引导加载kernel, 直接使用了宿主机的内核, 所以镜像启动很快

1. Docker命令

1.1 docker命令

  1. docker info # 查看docker的信息
  2. docker stats # 查看容器的内存和CPU

1.2 日志命令

  1. docker logs CONTAINER ID 查看对应容器的命令
  2. docker logs -tf CONTAINER ID 加上时间戳, 并动态展示
  3. docker logs --tail 10 CONTAINER ID 必须加上显示的行数

1.3 进程信息

  1. docker top CONTAINER ID 查看容器中的ID

1.4 元数据信息

  1. docker inspect df7d3fdddeee 既可以查看镜像, 也可查看容器

1.5 容器文件copy

  1. # 首先需要进入到Linux窗口
  2. docker cp 3e876b253a6b:/opt/my.txt /root/docs

2. 镜像命令

2.1 查看镜像

  1. docker serarch mysql # 查看远程镜像
  2. docker images # 查看本地镜像
  3. docker image -q # 只显示镜像ID
  4. docker history d969462cfd1c
  5. docker image inspect redis:latest

2.2 拉取镜像

  1. docker pull mysql # 拉取远程镜像到本地(默认是最后一个版本)
  2. docker pull mysql:5.6 # 下载指定版本的镜像(版本必须在dockerhub中存在)

2.3 移除镜像

  1. docker rmi mysql
  2. docker rim mysql `docker images -q` # 移除所有本地镜像

2.4 推送镜像

  1. # 首先需要登录dockerhub账号
  2. docker login -u pogusanqian

3. 容器命令

3.1 运行容器

  1. docker run centos 启动容器
  2. docker run -it centos 交互式命令启动(可以使用Ctrl + P + Q切换到主窗口)
  3. docker run --name=haha centos 给容器其名称叫做haha
  4. docker run -d centos 后台启动
  5. docker run -it --rm tomcat:9.0 启动tomcat容器, 容器停止后就会将容器删除
  6. docker run -p 8080:8080 tomcat 将容器的端口和服务器的端口联通(如果不指定, 外部是无法访问到容器中的端口的)
  7. docker run -P tomcat P表示随机映射端口
  8. # bash更好用一点, 按tab键会自动提示
  9. docker run -d centos /bin/bash -c "while true; do echo pogusanqian; sleep 1; done"
  10. # -e表示的是设置环境变量, 相当于是在配置文件中设置(句尾的\,表示一个链接符)
  11. docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" \
  12. -e ES_JAVA_OPTS="-Xms64m -Xms12m" elasticsearch:7.6.2
  13. # portainer 是一个可视化面板管理docker的
  14. docker run -d -p 3003:9000 \
  15. --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

3.2 查看容器

  1. docker ps 查看运行的容器
  2. docker ps -q 查看容器的容器ID
  3. docker ps -a 查看所有的容器(正在运行的 + 曾经运行的)

3.3 进入容器

  1. docker exec -it df7d3fdddeee /bin/sh 创建一个新的容器终端
  2. docker attach df7d3fdddeee 进入容器正在执行的终端

3.4 退出容器

  1. exit 退出容器
  2. Ctrl + P + Q 退出到主窗口(容器的端口并没有关闭)

3.5 停止容器

  1. docker start **** 启动容器
  2. docker restart *** 重启容器
  3. docker stop **** 停止容器
  4. docker kill *** 强制停止容器

3.6 销毁容器

  1. docker rm **** 删除容器(不能删除正在运行的容器)
  2. docker rm -f **** 强制删除容器
  3. docker rm $(docker ps -aq) 删除所有的容器(历史记录容器也会被删除)

3.7 提交容器

  • commit之后就会再本地创建一个镜像; 注意b055是容器ID

    1. docker commit -m "在webapp目录下, 补充项目" -a pogusanqian b055d6640827 mytomcat:1.0

    4. 数据卷命令

  • 数据卷挂载: -v 挂载, dockerfile挂载, —volumes-from(容器之间的关在)

  • 容器之间使用卷同步数据时, 只有当所有容器都不存在时, 这个卷才会被删除; 但是一旦使用-v同步到宿主机, 就算所有容器都销毁, 宿主机上的卷仍然存在

    4.1 指定路径挂载

    ```bash

    匿名挂载

    docker run -it -v /root/dockers/home:/home centos /bin/bash

注意conf.d是一个目录

docker run -p 3306:3306 -v /root/mysql-docker/conf:/etc/mysql/conf.d -v /root/mysql-docker/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123123 -d mysql

  1. <a name="AopvG"></a>
  2. ### 4.2 匿名/具名挂载
  3. ```bash
  4. # 具名挂在haha, 注意haha没有使用/开头
  5. docker run -it -v haha:/home centos /bin/bash
  6. # 匿名关在
  7. docker run -it -v /home centos /bin/bash

4.3 查看卷信息

  • 卷在宿主机实际路径: **/var/lib/docker/volumes** ```bash docker volume ls 查看所有的卷名称

docker volume inspect f740** 查看f740卷(匿名挂在的卷) docker volume inspect haha 查看haha卷的信息(具名挂载的卷)

  1. <a name="VGHqg"></a>
  2. ### 1.8 容器共享卷
  3. ```bash
  4. docker run -it --volumes-from b20a7d0df93d mycentos:1.0

4.9 卷权限

  1. # ro(readonly): 只读, 卷文件只能在宿主机上更改, 不能在容器中更改
  2. # rw(readwrite): 读写, 卷文件既能在宿主机上更改, 也能在容器中更改
  3. docker run -d -P -v nginx:/etc/nginx:ro nginx
  4. docker run -d -P -v nginx:/etc/nginx:rw nginx

5. DockerFile

  • dcokerfile是一个脚本, 运行起来可以生成镜像

    5.1 创建File

  • FROM: 基础镜像, docker中最小的镜像是**sratch**

  • MAINTAINER: 镜像维护者, 姓名+邮箱scratch
  • RUN: 镜像构建时, 需要运行的命令
  • ADD: 添加的内容
  • WORKDIR: 镜像的工作目录
  • VOLUME: 挂载的目录
  • EXPOST: 暴漏端口配置
  • CMD: 指定容器启动的时候, 运行的命令(只有最后一个会生效, 可被替代)
  • ENTRYPOINT: 指定容器启动时要运行的命令, 会追加
  • ONBUILD: 当构建一个被继承dockerfile, 这个时候就会运行onbulid指令
  • COPY: 类似ADD命令, 将我们的文件copy到镜像中
  • ENV: 构建的时候设置环境变量

    5.1.1 简单创建

    1. # 关键字推荐使用大写(#表示注释)
    2. FROM centos
    3. VOLUME ["volume01", "volume02"]
    4. CMD echo "-------end-------"
    5. CMD /bin/bash

    5.1.2 创建centos

    1. # centos这个镜像如果本地没有, 就会从hub中下载; 如果本地就会复用
    2. FROM centos
    3. MAINTAINER pogusanqian<pogusanqian@163.com>
    4. ENV MYPATH /usr/local
    5. WORKDIR $MYPATH
    6. RUN yum -y install vim
    7. RUN yum -y install net-tools
    8. EXPOSE 80
    9. CMD echo $MYPATH
    10. CMD echo "------end------"
    11. CMD /bin/bash

    5.1.3 创建tomcat

    ```bash FROM centos MAINTAINER pogusanqianpogusanqian@163.com copy readme.md /usr/local/readme.md

    将宿主机的jdk解压到容器中的/usr/local目录下

    ADD jdk-8u181-linux-x64.tar.gz /usr/local ADD apache-tomcat-9.0.56.tar.gz /usr/local

启动命令使用的时RUN, 不要写成ADD

RUN yum install -y vim

配置进入容器后的目录

ENV MYPATH /usr/local WORKDIR $MYPATH

配置jdk和tomcat路径

ENV JAVA_HOME /usr/local/jdk1.8.0_181 ENV CLASS_PATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.56 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.56 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

配置启动tomcat并将tomcat的日志进行输出到控制台(这里要使用F)

CMD /usr/local/apache-tomcat-9.0.56/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.56/logs/catalina.out

  1. ```bash
  2. docker build -t mytomcat:1.0 .
  3. # 启动容器将项目和日志挂载出来
  4. docker run -d -p 8080:8080 -v /home/dockers/mytomcat/webapps/test:/usr/local/apache-tomcat-9.0.56/webapps/test \
  5. -v /home/dockers/mytomcat/logs:/usr/local/apache-tomcat-9.0.56/logs mytomcat:1.0

5.1.4 创建koa

  1. FROM node:14-alpine
  2. RUN mkdir -p /home/Service/my-koa
  3. WORKDIR /home/Service/my-koa
  4. # .表示的是copy当前目录
  5. COPY . /home/Service/my-koa
  6. RUN npm install
  7. EXPOSE 3000
  8. CMD [ "npm", "start" ]

5.2 运行File

  • 如果dockerFile的文件名就叫做Dockerfile, 我们的-f参数可以不用写

    1. # 最后的.表示生成的镜像放在当前目录
    2. docker build -f ./dockerfile01 -t mycentos:1.0 .

    6. 网络通讯

  • https://blog.csdn.net/weixin_33905756/article/details/92454616

  • docker容器有四种网络模式
    • bridge: 桥接模式
    • none: 不配置网络
    • host: 和宿主机共享网络
    • container: 容器网络联通(已弃用)

image.png

6.1 Bridge模式

  • 只要安装docker, Linux服务器上就会多出一个虚拟网卡docker0; docker0主要用于桥接, 是用于docker容器的通讯
  • 当使用docker启动容器后, docker会使用evth-pair技术给容器分配一个ip
    • enth-pair技术是一对虚拟设备接口, 一端连着协议, 一端彼此相连
    • enth-pair相当于是桥梁, 连接各种虚拟网络设备
  • 容器之间的通讯时通过docker0作为桥接进行通讯
  • 宿主机和容器之间也是通过docker0作为桥接进行通讯 ```bash ip addr 查看本机的网络

启动连个tomcat容器

docker run -d -P —name tomcat01 tomcat docker run -d -P —name tomcat02 tomcat

tomcat容器中下载对应的指令

docker exec -it tomcat01 /bin/bash apt update apt install -y iproute2 apt install -y inetutils-ping

ping 172.17.0.2 # 宿主机和容器进行相互通讯(只能写ip地址, 不能写宿主机名字) docker exec -it tomcat01 ping 192.168.124.24 # 容器和宿主机进行通讯(相当于是先进入容器, 然后执行了ping命令) docker exec -it tomcat02 ping 172.17.0.2 # 容器之间相互通讯

  1. ![](https://cdn.nlark.com/yuque/0/2022/jpeg/2309174/1644720525248-88c589ff-a612-4b65-ab53-447a82106bf0.jpeg)
  2. <a name="JxIcB"></a>
  3. ### 6.2 Link链接
  4. - 在桥接模式中, 容器之间通讯只能使用ip地址, 但是又的服务场景需要使用服务名称进行通讯
  5. - --link可以时tomcat03链接tomcat01容器, 这样就可以直接使用容器名称寻址通讯
  6. - ink命令的本质其实就是修改了tomcat03容器的host.conf文件, 做了一次映射: `172.17.0.2 tomcat01 228152661c1b`
  7. - link命令不是互联的, tomcat03 link tomcat01, 只是修改了tom3host文件, tom1host文件并没有修改; 所以tom1不能直接ping tom3
  8. ```bash
  9. docker run -d -P --name tomcat03 --link tomcat01 tomcat # tomcat03 link tomcat01
  10. docker exec -it tomcat03 /bin/bash
  11. ping tomcat01 # 能根据容器名称ping通
  12. cat /etc/host.conf # 查看host文件

6.3 自定义网络

  • 使用自定义网络创建的容器是可以通过名称寻址的
  • 由于vmware创建的虚拟机的网址一般的都是192.168的网段, 所以使用docker创建网段的时候不要使用192.168, 不然会无法联网 ```bash docker network ls 查看docker中的所有网络 docker network inspect 126006eba4ff 查看网络元数据(126*不是容器id, 而是networkId)

创建自己的网络

docker network create —driver bridge —subnet 172.16.0.0/16 —gateway 172.16.0.1 mynet

删除网络

docker network rm mynet

使用自定义网络创建容器(—net的默认参数是bridge)

docker run -d -P —name tomcat-net-01 —net mynet tomcat

  1. <a name="G77Wb"></a>
  2. ### 6.4 网络联通
  3. - docker可以使用自定义网络创建不同的局域网, 不同的局域网之间是不能通讯的, 需要将不同的局域网进行打通
  4. - docker使用connect打通不同的局域网, 使不同局域网之间的容器可以通讯; connet命令的本质其实是将A容器挂载到了172.16局域网下, 这样A容器就有了两个容器地址
  5. ![](https://cdn.nlark.com/yuque/0/2022/jpeg/2309174/1644732215429-7a8e5ee9-1ca6-4d49-9628-5f7117024c1f.jpeg)
  6. ```bash
  7. # 创建局域网mynet
  8. docker network create --driver bridge --subnet 172.16.0.0/16 --gateway 172.16.0.1 mynet
  9. # 创建四个容器, 并启动
  10. docker run -d -P --name tomcat01 tomcat
  11. docker run -d -P --name tomcat02 tomcat
  12. docker run -d -P --name tomcat-net-01 --net mynet tomcat
  13. docker run -d -P --name tomcat-net-02 --net mynet tomcat
  14. # 进行容器联通, 此时tomcat01容器相当于放置在了两个局域网下, 这样tomcat就能和172.16局域网的容器进行通讯了
  15. docker network connect mynet tomcat01
  16. # 查看mynet网络配置(发现多了一个tomcat01的容器)
  17. docker network inspect fe90cc707ee0

9 常见错误

9.1 重启防火墙

image.png