Docker基础

215 阅读11分钟

前提准备

  • 腾讯云服务器

安装

参考官方文档

# 1.卸载旧版docker
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
                  
# 2.需要的安装包
sudo yum install -y yum-utils
​
# 3.设置镜像仓库
sudo yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    # https://download.docker.com/linux/centos/docker-ce.repo // 官方文档是国外的镜像,慢
    
# 4.更新yum软件包索引
sudo yum makecache fast
​
# 5.安装Docker ce是社区版,ee是企业版
sudo yum install docker-ce docker-ce-cli containerd.io
​
# 6.启动Docker
sudo systemctl start docker
​
# 7.hello-world
sudo docker run hello-world
​
# 如何卸载docker
 # 卸载依赖
 sudo yum remove docker-ce docker-ce-cli containerd.io
 # 删除资源
 sudo rm -rf /var/lib/docker
 sudo rm -rf /var/lib/containerd
​

Docker命令

帮助命令

docker version   # docker版本信息
docker info      # docker的系统信息,包括镜像合和容器数量
docker --help    # 帮助命令

镜像命令

docker images         # 本地镜像列表
docker search mysql   # 相当于在dockerhub上搜索mysql
docker pull mysql 下载镜像
Using default tag: latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete  # 分片下载
93619dbc5b36: Pull complete 
99da31dd6142: Pull complete 
626033c43d70: Pull complete 
37d5d7efb64e: Pull complete 
ac563158d721: Pull complete 
d2ba16033dad: Pull complete 
688ba7d5c01a: Pull complete 
00e060b6d11d: Pull complete 
1c04857f594f: Pull complete 
4d7cfa90e6ea: Pull complete 
e0431212d27d: Pull complete 
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest  # 真实地址,docker pull mysql 等价于 docker pull docker.io/library/mysql:latest
docker rmi 删除镜像
docker rmi -f 镜像id # 删除指定镜像
docker rmi -f $(docker images -aq) # 遍历删除全部的镜像

容器命令

说明:有了镜像才可以创建容器

接下来下载一个centos镜像来测试docker pull centos

新建容器并启动
docker run -it centos /bin/bash  # -it是进入到容器中 -d是后台启动
退出容器
exit
ctr + P + Q  # 退出不停止容器
列出容器
docker ps    # 列出正在运行的容器
-a           # 列出正在运行的容器+ 曾经运行过的容器
-n=1         # 列出最近创建的1个容器
-q           # 只列出容器的编号
删除容器
docker rm 容器id                     # 删除容器 正在运行的容器要加 -f 才能删除
docker rm -f $(docker ps -aq)       # 遍历删除所有容器
docker ps -a -q|xargs docker rm     # 利用管道删除所有容器
启动/停止容器
docker start 容器id
docker restart 容器id
docker stop 容器id     # docker stop,支持“优雅退出”。先发送SIGTERM信号,在一段时间之后(10s)再发送SIGKILL信号。Docker内部的应用程序可以接收SIGTERM信号,然后做一些“退出前工作”,比如保存状态、处理当前请求等。
docker kill 容器id     # docker kill,发送SIGKILL信号,应用程序直接退出。

其他常用命令

后台启动容器
docker run -d 镜像id  #后台启动容器 以centos为例,等价于docker run -d centos /bin/bash 
# 问题: 执行docker ps 发现容器已经停止了
# docker容器使用后台运行,就必须有一个前台进程,docker发现没有应用,就会立即停止
查看日志
docker logs -tf 容器id
# 为了不让后台启动的容器自动停止,写入执行脚本 
# docker run -d centos /bin/bash -c "while true;do echo longjun;sleep 1;done"
# docker logs 容器id # 不带参数获取执行时容器内输出的日志
# -t 显示日志输出时的时间
# -f 显示日志并持续获取后续输出的日志
# -n 10 获取10条日志
查看容器中进程信息
docker top 容器id
查看容器的元数据
docker inspect 容器id
进入当前运行的容器
docker exec -it 容器id bashShell  # 比如 docker exec -it d019caf20711 /bin/bash   #新开的终端
docker attach 容器id # 进入容器正在执行的终端
拷贝容器内文件到主机
docker cp 6e5e77da2b92:/home/helloworld.html /home # 将容器内/home/helloworld.html 文件拷贝到主机home文件夹内
docker内启动服务和主机端口联通
docker run -d -p 3355:8080 --name tomcat01 tomcat # 以tomcat为例 -p 3355:8080 就是把主机的3355端口和容器内的8080端口联通  注意需要放开主机防火墙的3355端口访问限制
# tomcat 镜像内webapps内没有内容,所以访问3355会显示http 404,需要进入容器,把webapps.dist文件夹内的所有文件复制到webapps中
docker exec -it tomcat01 /bin/bash
cp -r webapps.dist/* webapps
查看容器在主机的内存使用情况
docker stats
# 发现容器占用内存过大可以增加限制 如elasticsearch不加内存限制会达到2个多G,这里限制为64m-512m
# docker run -d --name elasticsearch01 --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.16.2
commit镜像
docker commit -a="longjun" -m="add webapps app" 容器id tomcat02:1.0 # 在本地生成一个新的镜像

使用数据卷

docker run -it -v /home/test:/home centos /bin/bash
# 以mysql为例使用数据卷
docker run -it -p 9001:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 注意mysql数据卷指向的主机目录/home/mysql/data内不能有mysql以外的内容,否则会报错

具名挂载和匿名挂载

docker run -d -P --name nginx01 -v /etc/nginx nginx
# -v 是挂载数据卷,一般冒号左侧目录是主机目录。冒号右侧目录是容器内目录,若只写一个目录则是容器内目录,主机目录由docker自动指定,这两种情况都是匿名挂载
# -P 当使用-P(大写)标记时,Docker会随机映射一个49000~49900的端口到内部容器开放的网络端口,端口可通过docker ps 查看
# 具名挂载:冒号左侧不是一个目录而是一个变量名 如 -v nginxVolume:/etc/nginx
docker volume ls # 查看所有的数据卷,匿名数据卷都是一长串编码
# DRIVER    VOLUME NAME
# local     3a1d1b0c7a1ca986282ee7aaf7a298556a5950ae1c0f4b25dc0a61f798dd4405
# local     37b05298d0c351400d866ad24911be4b9a8f279d1753ea3f12593df5bf5feffd
# local     225ac2f0268f77162aa7a9acdd7794421fba3efccd4facba4dcf04be79462c07
# local     599ba7f25f38ffa4e6c4967d56661b60319be7e6982d10bedf3e95491a74eaa3
# local     652a535d96dffa856156b099caa4ea412667fec38c9143992af0d5a07362bea6
# local     08895be143b5f363344676415c099955ff2830a39a64f266479174b34431f3f0
# local     d60138fe48ef1a46388fddf597c7c038b80a60949cc41aa989e4b86d2b5eb127
# local     f31e8a47d00d9b47f14d61fab9d63bbeed5701ef28e8aef9214983fbe78e4f51
# local     mingzi
docker volume inspect mingzi  # 查看数据卷相关信息
# [
#    {
#        "CreatedAt": "2022-01-19T21:53:30+08:00",
#        "Driver": "local",
#        "Labels": null,
#        "Mountpoint": "/var/lib/docker/volumes/mingzi/_data", # 数据卷主机目录,未指定主机目录的卷都会放在docker/volume目录下
#        "Name": "mingzi",
#        "Options": null,
#        "Scope": "local"
#    }
#]

DockerFile

dockerFile是用来构建镜像的构建文件。一个命令脚本,脚本的每一个命令就是镜像的一层

FROM centos

VOLUME ["volume01","volume02"]
CMD echo "--------end--------"
CMD /bin/bash

以上就是一个简单的dockerFile文件,在构建时就指定了两个匿名卷要挂载到主机

数据卷容器

# 通过--volumes-from 指定共享数据的容器
docker run -it --volumes-from testDockerFile01 --name testDockerFile02 longjun/centos 

DockerFile指令

FROM      # 基础镜像
MAINTAINER  # 镜像谁写的,姓名+邮箱
RUN       # 镜像构建时需要运行的命令
CMD       # 容器启动时要运行的命令,只有最后一个会生效,会被运行时的参数替换
ADD       # 添加压缩包,如tomcat镜像
WORKDIR   # 镜像的工作目录
VOLUME    # 挂载的目录
EXPOSE    # 保留端口配置
ENTRYPOINT  # 指定容器启动时要运行的命令,可以追加命令,不会被运行时的参数替换
ONBUILD   # 当构建一个被继承DockerFile时会允许ONBUILD的指令
COPY      # 类似ADD,将文件拷贝到镜像中
ENV       # 构建的时候设置环境变量

dockerFile.jfif

构建一个完整的centos

官方的centos只有基础的功能,没有vim,ifconfig等功能,可以自己构建一个

FROM centos
MAINTAINER longjun<228089xxxx@qq.com>

ENV MYPATH /user/local 
WORKDIR $MYPATH # 设置工作目录(进入容器默认进入的目录)

RUN yum -y install vim # 安装vim
RUN yum -y install net-tools # 安装ifconfig相关的指令

EXPOSE 80

CMD echo $MYPATH
CMD echo "--------end--------"
CMD /bin/bash

CMD 和 ENTRYPOINT 的区别

  • CMD命令运行时的参数会把它替换掉
  • ENTRYPOINT命令可以在运行时通过参数追加,而不会被替换
# 测试dockerFile。将CMD替换为ENTRYPOINT对比测试,运行时增加参数 -l
FROM centos
CMD ["ls","-a"]

link 容器间网络互通

  • 每创建一个容器docker0网络(172.17.0.1/16)都会给主机和该容器各分配置一个ip用于容器和主机的联通
  • 容器间也可以通过容器的ip进行联通,但本质上还是经过主机桥接进行联通
  • 通过容器名访问:通过 --link 容器2 可以直接通过容器名连通对应容器(其实就是在host配置中添加了容器2的ip),注意这里只是单向连通

自定义网络

查看所有网络docker network ls,docker0就是bridge(桥接)网络模式

NETWORK ID     NAME          DRIVER    SCOPE
b6d5f1a29898   bridge        bridge    local
3203efb39ec4   host          host      local
7732bb6babe6   none          null      local
4e67d2610a72   somenetwork   bridge    local

--net bridge 正常启动一个容器会有默认参数--net bridge 即使用docker0网络,我们也可以改成我们自己创建的网络

创建自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gatway 192.168.0.1 mynet
# --driver bridge 使用桥接网络模式
# --subnet 192.168.0.0/16 子网网段192.168.0.2 - 192.168.255.255
# --gateway 192.168.0.1 网关
创建容器使用自定义网络
# 启动两个tomcat容器并连接mynet
docker run -d -P --name tomcat-net-01 --net mynet lj996/tomcat
docker run -d -P --name tomcat-net-02 --net mynet lj996/tomcat

查看mynet网络详细docker network inspect mynet

[
    {
        "Name": "mynet",
        "Id": "d402792af1ad4cee67b934bb597377863a5d0cde4f61fe00c2eb513a2752a154",
        "Created": "2022-02-19T11:32:13.820610538+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16", # 创建时设置的网段
                    "Gateway": "192.168.0.1" # 创建时设置的网关
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": { # 所有连接的容器ip明细
            "1a9b96d7013c55e82cfc079f1714deb602a6fd751e63e91eccb109aba4c4e6ba": {
                "Name": "tomcat-net-01",
                "EndpointID": "7b607d9b7c49a302467cf21619d0612569233e21e6f92d83e0661882bcdde983",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "5bd3d0a7f87178c17fb9bfbe460601a17eb4393d18584568dbf91d0df3677c4d": {
                "Name": "tomcat-net-02",
                "EndpointID": "7378f6ad85a7cce79d9ffb00fb4fe8c07b8e8ba18853ea0df776e6268fdfcac0",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
容器连通
  • 同网络容器连通 docker0网络容器间需要通过ip连通,或者使用--link才能通过容器名连通,而且还只是单向连通 自定义网络即能通过ip,也能通过容器名连通,无需--link
docker exec -it tomcat-net-01 ping tomcat-net-02
# ping不通应该是容器内没有ping命令,可以先进入容器安装apt-get update && apt-get install iputils-ping(由于docker在制作时,精简了apt的仓库信息。因此使用前需要update),安装完在ping就可以了
  • 不同网络容器连通 通过docker0创建的容器和通过mynet创建的容器怎么连通呢,因为不同网段应该是不可能连通的

换个思路,既然不同网段不能连通,那就加入到同一个网段

# 先创建一个docker0网络的容器
docker run -d -P --name tomcat-01 lj996/tomcat
# 将tomcat-01容器和mynet网络连接
docker network connect mynet tomcat-01

此时容器tomcat-01同时在docker0和mynet网络中,有两个ip地址,这样该容器就能连通两个网络中所有的容器