Docker基本使用

0 阅读19分钟

服务器基础配置

  1. WindTerm连接云服务器(记得在属性配置中的SSH的连接选项里设置定时发送包并保存防止断连)

  2. 卸载旧版docker: sudo是以管理员权限运行

    sudo yum remove docker \
        docker-client \
        docker-client-latest \
        docker-common \
        docker-latest \
        docker-latest-logrotate \
        docker-logrotate \
        docker-engine \
        docker-selinux
    
  3. 安装yum的utils库:

    yum是包管理器,这个是系统自带的,CentOS是yum,Ubuntu是atp

    install -y是下载并自动确认,因为如果直接install他下载完成后会让你输入y/n确认

    yum-utils就是要下载的扩展包,这个包是后面用来配置阿里云仓库,并不是必须的

    sudo yum install -y yum-utils
    
  4. (可选) 备份原repo文件

    mv就是move移动,把文件移动(重命名)

    /etc/yum.repos.d/CentOS-Base.repo文件原地址

    /etc/yum.repos.d/CentOS-Base.repo.backup文件新地址(及重命名)

    sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
    
  5. 下载阿里云的配置文件,之所以要把原repo改为阿里云repo是因为国外的在国内太慢了而且容易被墙

    curl : 发送HTTP/HTTPS请求并获取内容,这里用来下载阿里云上的repo文件

    -o /etc/yum.repos.d/CentOS-Base.repo, -o是用来指定文件输出地址,即把下载内容保存到指定文件里,如果该文件已存在就覆盖

    mirrors.aliyun.com/repo/Centos…, 阿里云repo的获取位置

    注意这种方式不需要yum-utils库,直接就能用

    sudo curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    

    另一种下载方式: 上面curl的方式安装需要自己保证名字什么的是正确的,用下面这个命令可以直接由yum-utils自动指定库和生产的文件名,但是注意这个依赖yum-utils包,需要先下载

    sudo yum-config-manager --add-repo http://mirrors.aliyun.com/repo/Centos-7.repo
    
  6. 清空旧缓存

    sudo yum clean all
    

    下载缓存清单 : 相当于是仓库(我们用的阿里云)中的商品清单,因为更换成了阿里云镜像需要重新下载一次,fast表示只建立必要的

    sudo yum makecache fast
    

docker配置

  1. 从阿里云下载docker CE的官方仓库配置文件,注意前面已经配置过阿里云repo,但是这个repo是系统的基础repo,用于utils等包,而docker是第三方,不包含在基础repo里,所以需要单独下载配置文件,这样之后才能下载docker,否则会找不到docker下载源

    sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
  2. 将刚刚下载下来的配置文件中的下载地址修改为阿里云的Docker镜像地址

    sudo sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
    
  3. 安装docker

    docker-ce是docker社区版核心引擎

    docker-ce-cli是docker命令行工具

    containerd.io:容器运行时,Docker 依赖它来管理容器的生命周期

    docker-buildx-plugin:Docker Buildx 插件,用于扩展镜像构建能力(如多平台构建)

    docker-compose-plugin:Docker Compose 插件,用于定义和运行多容器应用(替代原 docker-compose 独立命令)。

    yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
  4. 启动与校验

    #查看Docker版本
    docker -v
    # 启动Docker
    systemctl start docker
    #列出运行在本地Docker主机上的所有镜像
    docker images
    # 停止Docker
    systemctl stop docker
    # 重启
    systemctl restart docker
    # 设置开机自启
    systemctl enable docker
    # 列出所有正在运行的容器
    docker ps
    
  5. 配置加速源: 刚刚配置的是下载docker平台的阿里云加速,现在要配置拉取docker上镜像的加速,要不然之后拉取镜像都从dockerhub上拉取特别慢

    # 创建目录,mkdir是创建目录,但是需要保证父目录都存在加上-p之后不存在的父目录会被自动创建,存在的话也不会报错,因为Docker 的配置文件默认放在 /etc/docker/daemon.json,所以需要确保这个目录存在。
    mkdir -p /etc/docker
    # tee是把内容写入到指定的/etc/docker/daemon.json文件中,<<-'EOF'是将后续内容原样传给tee直到遇见结束符EOF,-表示忽略每一行行首制表符,下面的地址会在下载的时候被docker依次尝试
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": [
      "https://7i1sxv6h.mirror.aliyuncs.com",
      "https://docker.mirrors.ustc.edu.cn",]
    }
    EOF
    # 重新加载配置
    systemctl daemon-reload
    # 重启Docker
    systemctl restart docker
    

docker常用命令

  1. 检索: docker search 镜像名 搜索是否有这个镜像,注意docker search是不走镜像加速器直接从Docker Hub上搜索的,所以可能遇见超时的情况,可以直接去docker Hub上搜索然后直接下载

  2. 下载: docker pull 镜像名 ,下载指定镜像,注意这里如果直接写nginx这样的镜像名是默认下载最新版本的,相当于docker pull 镜像名:latest,如果想指定版本需要自己去Docker Hub上找到想要的的版本然后docker pull 镜像名:版本

  3. 查看下载的镜像列表: docker images

  4. 查看正在运行的容器列表: docker ps, 参数:

    1. 查看所有: docker ps -a是查看所有容器(包括没运行的)
    2. 查看ID: docker ps -q 是查看运行中容器的id跟上面一起用就是查看所有容器的ID
  5. 删除镜像: docker rmi 镜像名:版本号 ,注意删除必须指定版本号,比如docker rmi nginx:latest,也可以docker rmi 唯一ID,这个唯一ID可以docker images查看,每一个镜像都有一个唯一ID

  6. 创建并启动容器: docker run 镜像名:版本号 , 基于指定镜像创建并启动一个容器,如果没有这个镜像,会自动从仓库拉取,注意这就意味着假设我们执行docker run nginx那他不会去运行我们已经有的nginx:1.26.0镜像而是找是否有nginx:latest,没有的话去hub拉取,另外docker run每次运行都会创建一个新容器,而docker start是用来运行已经存在的容器的

    注意下面的这些参数都可以组合使用

    1. 后台启动参数: docker run -d 镜像名:版本号

    2. 指定容器名参数: docker run --name 自定义的容器名 镜像名:版本号

    3. 端口映射: docker run -p 外部端口号:内部端口号 镜像名:版本号,注意一个容器是由自己的一套小Linux系统的,即上面的端口号都是自己的,而这些容器都运行在服务器上,服务器有自己的端口号,也就是说假如我现在要运行一个nginx应用,应用的端口号指定的是80,这个端口号是内部容器系统的端口号,而在网络上输入url试图访问的是外部服务器的端口号,所以需要把外部服务器端口号映射到内部容器的端口号,(PS:如果没有效果记得去看看自己的云服务器安全组是否放行了指定端口)

      另外如果启动其他容器,内部端口号可以是一样的,因为不同容器之间的环境是隔离的,但是外部端口号不能是一样的,因为只有这么一个服务器

    4. 目录挂载: docker run -v 外部目录:容器内目录,因为直接修改镜像内的内容很不方便而且如果镜像出问题的话删除镜像再重建之后之前那些改动就都没有了,所以现在在服务器的指定文件夹创建项目并映射给镜像,下载再创建以相同方式映射就可以了,比如docker run -d -p 88:80 -v /home/testdocker/html:/usr/share/nginx/html就是我自己创建/home/testdocker/html映射到镜像内/usr/share/nginx/html文件夹.这样启动镜像在访问/usr/share/nginx/html的内容的时候实际上是访问/home/testdocker/html的内容,并且这个文件夹在服务器里保存着,镜像不管怎么销毁重建只要创建的时候映射这个文件夹效果都一样,但是注意要确保这个文件夹存在

    5. 卷映射: docker run -v 卷名:容器内目录,卷名不是绝对路径而是相对路径,比如docker run -v nconf:/etc/conf,这个卷(实际上是一个目录)会被默认存放在/var/lib/docker/volumes/卷名位置,卷映射和目录挂载的区别是目录挂载是直接以外部目录为准的,而卷映射是先看卷中有无内容,如果没有就把容器内文件夹下的内容赋值到卷内,之后就跟目录挂载没区别了,如果一开始有内容那就相当于目录挂载了其实

      查看卷: docker volume ls

      删除卷: docker volume rm 卷名

    6. 指定要连接到的网络: docker run -network 网络名

    7. 启动时设置环境变量: docker run -e 环境变量名=环境变量值

  7. 停止容器: docker stop 容器名 ,使用docker ps -a查看到的容器名或是容器ID都可以用来停止容器

  8. 启动容器: docker start 容器名,用法跟停止容器完全一样

  9. 重启容器: docker restart 容器名,用法跟上面一样

  10. 查看容器状态: docker stats 容器名, 用法跟上面一样

  11. 查看容器日志: docker logs 容器名, 用法跟上面一样

  12. 删除容器: docker rm 容器名, 用法跟上面一样,注意区别docker rmi 镜像名:版本号,这个是删除镜像的,另外这个必须停止容器之后才能删除容器,如果想直接删除容器可以docker rm -f 容器名

  13. 进入容器: docker exec 进入模式参数 容器名 交互方式,比如docker exec -it mynginx /bin/bash命令中-it代表交互模式,mynginx是容器名,/bin/bash表示以控制台的方式交互

    进入之后用ls /可以列出目录结构

    之后可以cd到要控制的页面所在的目录下,比如cd /usr/share/nginx/html/可以进到nginx的默认入口文件存放的目录下 (注意是usr不是user) ,

    echo命令:用于往终端中输出字符串或变量的值可以用来测试交互是否正常

    1. 输出固定文本: echo "内容"
    2. 输出变量内容: echo $变量名,比如echo $PATH
    3. 将内容写入文件: echo "新内容">文件名,这里>是覆盖,如果是>>表示追加,新内容不但可以写字符串,还能写标签等
  14. 提交镜像: docker commit 容器名 自定义的新镜像名:自定义的镜像版本号,这个就是把指定的容器保存为一个新镜像,存在自己的服务器上(不是提交到仓库而是保存到自己的服务器上) ,比如我拉取容器之后对他进行改动,现在想把改动完的传上去就这么传

    有一些提交参数:

    1. 作者: docker commit -a "作者信息,比如 John <Jon@qq.com>" 容器名 镜像名:版本
    2. 提交时应用Dockerfile指令: -c
    3. 提交信息: -m
    4. 提交期间暂停容器: -p=true,默认是true,如果设置false则提交期间不会暂停容器,可能会导致状态不一致
  15. 保存为tar包: docker save -o 文件保存位置 镜像名:版本,注意这里的文件保存位置如果只写文件名比如test.tar那会默认保存到当前目录,如果想指定目录可以写绝对路径比如/home/rowlinc/test.tar ,但是必须保证目录需要存在,最好先用mkdir -p创建一下,保存之后这个tar包就被保存到指定位置了,这个包可以随便拷给别人用

  16. 加载镜像: docker load -i 文件包位置,把从别人那拷的tar包存到自己服务器上,然后运行这个命令比如docker load -i /home/rowlinc/testdocker01.tar他就会把这个tar包映射为一个镜像

  17. 分享镜像到Hub: docker login这个是将镜像分享到docker hub上,需要你有docker的账户,执行命令后会要求你输入账户和密码,但是注意由于docker hub是国外的所以很多时候是连接不上的,这里我用的是阿里云的docker hub,在阿里云=>控制台=>容器与镜像服务=>实例列表中,先创建命名空间,这个命名空间相当于是告诉别人这些仓库是谁的/哪个组织的,创建之后创建镜像仓库,一般一个仓库存放一个镜像的不同版本,创建完之后可以查阅你仓库地址,执行阿里云提供的命令(类似于docker login --username=你的用户名 地址,具体命令自己到镜像仓库详情页查看)即可连接到这个仓库

  18. 给镜像改名: docker tag 原镜像名:版本 新镜像名:版本,因为镜像上传的标准格式是要求 用户名/镜像名:版本,所以之前镜像名:版本的名字需要改一下,注意tag命令不是新创建一个镜像,你images查看就会发现有两个不同名的镜像但是他们的ID是一样的,注意阿里云的推送依然是不一样的,具体自己到仓库里查阅

  19. 推动镜像到仓库: docker push 镜像名:版本号,注意一般推送正常版本的同时最好给最新版制作一个latest的tag因为很多人拉镜像都直接docker pull 镜像名,阿里云依旧不一样,自己去仓库查,另外注意不要用镜像id推送镜像,因为不同tag的镜像id是一样的,注意镜像名跟仓库名需要一致,docker推送会推送到镜像名对应的仓库中,如果当前不存在这个仓库会自动创建

  20. 创建容器网络: docker network create 自定义的网络名,因为服务器内部不同网络通信可以通过访问外部ip加外部端口访问内部其他容器,但是这样一来相当于绕路了,所以一般不这样做,而是内部直接进行访问,因为内部不同容器之间是通过一个内网连在一起的,所以通过内部网络的网络ip+内部端口(注意是容器端口不是服务器端口,因为这是内部通信)即可访问,但是因为默认网络没有DNS解析服务,所以只能通过ip访问不能通过域名访问,而关闭容器再启动的时候ip就变了,所以需要自己创建一个容器网络,然后运行容器的时候让他连接到这个网络来,这样就有DNS解析服务,可以直接通过容器名+容器端口来访问了,并且容器重启由于容器名没变还是可以照样连

部署自己的应用

以springboot+mysql+vue项目为例

springboot:

  1. 将项目打成jar包

  2. 将jar包传到云服务器上: scp -P 22 "你的jar包的绝对路径" root@你的服务器公网IP:要传到的云服务器目录如/root/,在自己的电脑的终端运行这个命令

  3. 在本地编写dockerfile再传到云服务器上或者直接在云服务器jar包旁边创建Dockerfile编写

    FROM docker.xuanyuan.run/library/eclipse-temurin:21.0.10_7-jre-ubi10-minimal
    #基础环境,dockerhub上是openjdk:21,但是国外的很难访问,这是由国内代理的
    LABEL authors="Rowlinc"
    #标签,用来标识作者等
    COPY recommendation-demo01-0.0.1-SNAPSHOT.jar /app/recommendation.jar
    #这是构建的时候将这个jar包复制到镜像里的/app目录下,注意这个/app目录是新创建的镜像里的目录不是宿主机主环境的目录
    EXPOSE 8080
    #指定暴露端口
    ENTRYPOINT ["java", "-jar","/app/recommendation.jar"]
    #指定镜像的启动命令,也可以写成java -jar /app/recommenation.jar,不过建议写成数组模式
    
  4. 然后运行命令制作镜像: docker build -f 你的Dockerfile地址 -t recommendation:v1.0 .注意最后有一个"."这表示打进镜像的是当前包里的东西,你的Dockerfile地址,如果当前就在Dockerfile所在的文件夹下就直接写Dockerfile就行,-t是指定打出来的镜像的名字和版本

    注意jdk有可能下不下来,因为docker被国内封掉了,这里推荐轩辕镜像或者自己下载二进制文件然后自己制作镜像

vue: 前端的静态文件需要托管在nginx里,有两种方式,第一种是拉下来nginx镜像,把nginx内部目录映射到服务器的静态文件目录上,第二种是把静态文件直接复制到nginx镜像里打包成一个镜像,这里以第二种举例

  1. 将vue项目打包成一个dist文件夹

  2. 进入到dist目录,将dist目录里的内容打包成zip文件: zip -r ../my-vue-app.zip *,可能这个命令无法使用,在Window PowerShell中可以用下面这个命令Compress-Archive -Path * -DestinationPath ../vue-app.zip,Compress-Archive是内部命令,-Path是指定要压缩的内容,*表示当前文件夹下所有的文件夹(包括子目录),-DestinationPath指定压缩包输出的位置,../vue-app.zip就是当前文件夹的父文件夹下

  3. 打包完之后依然是用scp命令推送到服务器上

  4. 在服务器上将压缩包解压到指定位置: unzip 压缩包位置 -d 解压文件存放的目录,注意这个命令需要先下载unzip包,命令为yum install -y unzip

  5. 假如解压的文件(一般是index.html和assets)存放位置是/resources/vue/dist/里,那么可以在/resources/vue里编写Dockerfile和nginx.conf,在Dockerfile中需要把dist目录下的内容复制到nginx的启动文件夹中,nginx.conf文件复制到nginx的配置文件夹

    Dockerfile:

    #基础镜像nginx,但是由于现在很难拉下来,建议先自己拉取nginx镜像然后用docker build --pull=false来阻止构建镜像的时候再次拉取基础nginx镜像
    FROM nginx:alpine
    LABEL author="作者名"
    #将dist目录下所有文件复制到nginx内部的入口目录
    COPY ./dist /usr/share/nginx/html
    #将自制的nginx配置文件复制到nginx自己默认配置文件的位置,即会覆盖掉原来的配置文件
    COPY nginx.conf /etc/nginx/conf.d/default.conf
    #nginx启动的默认端口是80,这里声明容器启动的时候监听的端口
    EXPOSE 80
    #这个是让nginx容器不在后台运行而是前台运行
    CMD ["nginx", "-g", "daemon off;"]
    

    注意这里之所以让nginx容器在前台运行,是因为nginx容器启动默认是后台运行,他会在启动之后关闭主线程,用子线程来处理事务,但是docker在发现容器没有主进程的时候会默认容器没有运行就会退出

    nginx.conf:

    # 虚拟主机配置(精简版,适用于个人项目)
    server {
        # 监听 80 端口(HTTP)
        listen 80;
        # 服务器域名或 IP,可改为你的域名,未配置时用 localhost
        server_name 域名/IP;
    ​
        # 静态文件根目录(Vue 构建产物存放位置)
        root /usr/share/nginx/html;
        # 默认首页
        index index.html;
    ​
        # ----------------------------------------------
        # 1. 处理 Vue Router history 模式(刷新不 404)
        # ----------------------------------------------
        location / {
            # try_files 按顺序查找:
            # 1. $uri:请求的文件是否存在
            # 2. $uri/:请求的目录是否存在
            # 3. 如果都不存在,则返回 /index.html,让 Vue Router 接管路由
            try_files $uri $uri/ /index.html;
        }
    ​
        # ----------------------------------------------
        # 2. API 反向代理(解决跨域,将 /api 请求转发到后端)
        # ----------------------------------------------
        location /api/ {
            # 后端服务地址(根据实际情况修改)
            # 如果后端在 Docker 容器中且与 nginx 在同一网络,可用容器名:端口
            proxy_pass http://后端的服务名:8080;
            # 传递原始请求头,让后端获取真实信息
            #把浏览器中输入的域名原封不动的传给后端服务器
            proxy_set_header Host $host;
            #将客户端的真实IP传给后端
            proxy_set_header X-Real-IP $remote_addr;
            #每经过一层代理就把IP地址追加到列表末尾
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    ​
        # ----------------------------------------------
        # 3. 静态资源长缓存(提升性能)
        # ----------------------------------------------
        location ~* .(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
            # 设置过期时间为 1 年
            expires 1y;
            # 添加 Cache-Control 头,public 表示可被任何缓存存储,immutable 表示文件不会变化
            add_header Cache-Control "public, immutable";
            # 关闭访问日志,减少磁盘写入
            access_log off;
        }
    ​
        # ----------------------------------------------
        # 4. Gzip 压缩配置(减少传输体积,加快加载速度)
        # ----------------------------------------------
        # 开启 gzip 压缩
        gzip on;
        # 添加 Vary: Accept-Encoding 头,告知缓存服务器根据客户端是否支持压缩缓存不同版本
        gzip_vary on;
        # 对代理请求也进行压缩
        gzip_proxied any;
        # 压缩级别(1-9),6 是性能与压缩率的平衡点
        gzip_comp_level 6;
        # 指定压缩的 MIME 类型(文本类、JS、CSS、JSON、SVG 等)
        gzip_types text/plain text/css text/xml text/javascript 
                   application/json application/javascript application/xml+rss 
                   application/x-javascript image/svg+xml;
    }
    
  6. 然后制作镜像就行了

用compose.yaml来批量启动多个容器

  1. compose.yaml的编写:

    compose.yaml:

    #应用名
    name: recommendation-app
    services:
      #服务名
      mysql:
        #容器名,如果不指定的话默认是服务名
        container_name: mysql
        #指定镜像
        image: mysql:8.0
        #指定服务器端口与容器端口的映射
        ports:
          - "3306:3306"
        #环境变量,外部环境变量会覆盖掉内部的环境变量
        environment:
          - MYSQL_ROOT_PASSWORD=你的数据库密码
          #这个配置会在数据库启动的时候创建一个数据库
          - MYSQL_DATABASE=要新创建的数据库名字
        #卷映射,mysql一般需要把数据映射到服务器的其他位置,这样才不会在容器被删除的时候丢失数据
        volumes:
          - mysql-data:/var/lib/mysql
          - /data/database/recommendation:/etc/mysql/conf.d
        #重启
        restart: always
        #指定所在的网络,因为需要在同一网络下才能让各个容器互联
        networks:
          - recommendation
      recommendation:
        container_name: recommendation
        image: recommendation:v1.0
        ports:
          - "8080:8080"
        environment:
          - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/recommendation
          - SPRING_DATASOURCE_USERNAME=用户名
          - SPRING_DATASOURCE_PASSWORD=密码
          - FILE_ROOT_DIRECTORY=/data/file/student
          - SWAGGER_SERVICE_URL=http://IP地址:8080
        volumes:
          - /data/file/student:/data/file/student
        restart: always
        networks:
          - recommendation
        #因为运行后端需要先启动mysql所以指定依赖,所以指定依赖
        depends_on:
          - mysql
      recommendation-vue:
        container_name: recommendation-vue
        image: recommendation-vue:v1.0
        ports:
          - "80:80"
        restart: always
        networks:
          - recommendation
        depends_on:
          - recommendation
    #目录挂载不需要,但是卷映射需要在外面指定
    volumes:
      mysql-data:
    #创造网络
    networks:
      recommendation: