欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Docker学习笔记(配置镜像加速,持续更新中)

程序员文章站 2022-05-11 17:21:47
...

title: Docker基础
date: 2020-03-19 10:29:51
categories: 微服务基础设施


  • 虚拟机里不能装虚拟机,但可以装Docker
  • 镜像和容器的关系类似于类与对象
  • 容器之间独立,(隔离机制)(沙箱机制)
  • docker由C/S结构组成,我们的命令去请求服务端,服务端返回请求结果

使用脚本自动安装 Docker

在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Ubuntu 系统上可以使用这套脚本安装:

$ curl -fsSL get.docker.com -o get-docker.sh
# 可能会出现 404 错误,请移步下面的特别说明
$ sudo sh get-docker.sh --mirror Aliyun

执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker CE 的 Edge 版本安装在系统中。

2018 年 7 月 21 日,貌似阿里云这边在做调整,故导致 Docker 的 Aliyun 安装脚本不可用,是永久性还是临时性的尚不清除,如果你已经按照之前的操作安装 Docker,请按以下步骤进行修复并重新安装

  • 如果已经使用了 Aliyun 脚本安装并成功的
    • 请先卸载 Docker,命令为:apt-get autoremove docker-ce
    • 删除 /etc/apt/sources.list.d 目录下的 docker.list 文件
  • 使用 AzureChinaCloud 镜像脚本重新安装,命令为:sudo sh get-docker.sh --mirror AzureChinaCloud

配置镜像加速器

请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件)(第二个位置为私服Registry)

{
  "registry-mirrors": [
    "https://qy5lms4s.mirror.aliyuncs.com"
  ],
  "insecure-registries": [
    "172.18.48.57:5000"
  ]
}

注意,一定要保证该文件符合 json 规范,否则 Docker 将不能启动。

之后重新启动服务。

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

注意:如果您之前查看旧教程,修改了 docker.service 文件内容,请去掉您添加的内容(--registry-mirror=https://registry.docker-cn.com),这里不再赘述

Docker镜像

下载

docker pull tomcat
docker pull tomcat:9-jre8
docker pull ip:port/tomcat:9-jre8

列出本地镜像

docker images
docker image ls
  • 镜像下载的是压缩体积大小
  • 可以通过以下命令来便捷的查看镜像、容器、数据卷所占用的空间
docker system df
  • 列出部分镜像
docker image ls ubuntu

启动

  • 启动tomcat (启动一次新建一个容器)
docker run -p 8088:8080 (--name mytomcat(容器名)) tomcat:9-jre8    
(将Tomcat的8080端口映射到宿主机的8088端口)

docker run -P(大写) tomcat:8-jre8 (宿主机随机端口,docker端口由EXPOSE决定)
  • 启动Ubuntu (启动一次新建一个容器)
$ docker run -it --rm \
    ubuntu:16.04 \
    bash

[email protected]:/# cat /etc/os-release

-it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。(将主线程交给Docker)
--rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
ubuntu:16.04:这是指用 ubuntu:16.04 镜像为基础来启动容器。
bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash

虚悬镜像

<none>               <none>              00285df0df87        5 days ago          342 MB

要删除

$ docker image prune

无互交模式时

docker rmi $(docker images -q -f dangling=true)

镜像更新

docker pull ubuntu:16.04

删除镜像

如果该镜像还有容器没有删除,先删除容器

docker image rm [选项] <镜像1> [<镜像2> ...]
docker rmi <镜像1> [<镜像2> ...]

docker image rm 4e7840b49fad
docker rmi tomcat:8-jre8

使用 DockerFile 定制镜像

DockerFile定制镜像

  • 将我的应用程序打包到镜像里,然后可以到处运行
  • 像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建
  • 首先在 /usr/local 目录下新建一个docker 文件夹,再建一个tomcat文件夹,最后建立一个文本文件Dockerfile

Dockerfile脚本

  • 一个定制tomcat的简单例子
FROM tomcat:8-jre8

WORKDIR /usr/local/tomcat/webapps/ROOT/
RUN rm -rf *
RUN echo "hello docker! hello world!" > /usr/local/tomcat/webapps/ROOT/index.html

构建定制对象

  • 构建镜像
docker build -t qblog .

将当前目录打包成压缩包,传到服务端
  • 镜像构建上下文(Context)

上文的构建命令表示 :把当前目录大包为上下文,传到服务端

表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举,这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎(通过REST API),这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。

如果在 Dockerfile 中这么写:

COPY ./package.json /app/

这并不是要复制执行 docker build 命令所在的目录下的 package.json,也不是复制 Dockerfile 所在目录下的 package.json,而是复制 上下文(context) 目录下的 package.json

一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个 .dockerignore,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。

Dockerfile指令

  • FROM

    • 指定基础镜像(在那个镜像的基础上定制)

    • FROM tomcat:8-8jre
      
  • RUN

    • 用来执行命令行命令(shell格式)

    • RUN echo "hello docker!" > /usr/local/tomcat/webapps/ROOT/index.html
      
  • WORKDIR

    • 用来指定工作目录,可以是Dockerfile 的命令执行目录,或者是bash的默认目录

    • WORKDIR /usr/local/tomcat/webapps/ROOT/
      
      //再次进入容器
      [email protected]:/usr/local/docker/tomcat# docker run -it --rm qblog2 bash
      [email protected]:/usr/local/tomcat/webapps/ROOT#
      

    之前说过每一个 RUN 都是启动一个容器、执行命令、然后提交存储层文件变更。第一层 RUN cd /app 的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。因此如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR 指令。

  • COYP

WORKDIR /usr/local/tomcat/webapps/ROOT

COPY my-shop-web-admin-1.0.0-SNAPSHOT.zip .
  • ADD

    • 可以自动解压缩 tar 包

    • 更高级复制,比如 <源路径> 可以是一个 URL,这种情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去。下载后的文件权限自动设置为 600,如果这并不是想要的权限,那么还需要增加额外的一层 RUN 进行权限调整,另外,如果下载的是个压缩包,需要解压缩,也一样还需要额外的一层 RUN 指令进行解压缩。所以不如直接使用 RUN 指令,然后使用 wget 或者 curl 工具下载,处理权限、解压缩、然后清理无用文件更合理。因此,这个功能其实并不实用,而且不推荐使用

  • CMD

    • 用来启动镜像里面的程序
  • ENTRYPOINT

  • ENV

  • VOLUME

  • EXPOSE

    • EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口

Docker 容器

列出Dockers容器及信息

docker ps -a

启动或暂停一个已存在的容器

docker start(stop) 5f7f86902b8c

删除容器和 批量删除

docker rm 2a0c11797f39

//删除所有未运行的容器
docker rm $(sudo docker ps -a -q)

//强行删掉一个容器
[email protected]:/usr/local/docker/mysql/conf# docker rm -f mysql

守护态运行

在后台运行,不占用控制台主线程

//启动第一个容器
[email protected]:/usr/local/docker/tomcat# docker run -p 8088:8080 --name swing-tomcat -d tomcat:8-jre8 
f100430594dd9700ea36f6f0d03e34378f4a80923a19aacacf3e0706f8dad008

//启动第二个容器
[email protected]:/usr/local/docker/tomcat# docker run -p 8089:8080 --name swing-tomcat2 -d tomcat:8-jre8 
cb851d2775fd6214237acf4429c270604418aa137cc812e66a6be2b2e053c502

以bash的方式进入容器

docker exec -it ddfa08d12284 bash

数据卷

数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷 可以在容器之间共享和重用
  • 数据卷 的修改会立马生效
  • 数据卷 的更新,不会影响镜像
  • 数据卷 默认会一直存在,即使容器被删除

注意:数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的 数据卷

实例:

[email protected]:/usr/local/docker/tomcat# mkdir ROOT
[email protected]:/usr/local/docker/tomcat# cd ROOT/
[email protected]:/usr/local/docker/tomcat/ROOT# vi index.html

[email protected]:/usr/local/docker/tomcat/ROOT# docker run -p 8082:8080 --name volumetest -d \
> -v /usr/local/docker/tomcat/ROOT:/usr/local/tomcat/webapps/ROOT tomcat:8-jre8
261ab7efe7e89b77efec51b9fd2e67fc4379daa72a4b95d5fefff31c03e4d5e0

Docker构建MySQL

  • MySQL 8.0 :InnoDB 支持事务 效率也提高了,支持原生分布式解决方案
docker run -p 3308:3306 --name mysql \
-v /usr/local/docker/mysql/conf:/etc/mysql \
-v /usr/local/docker/mysql/logs:/var/log/mysql \
-v /usr/local/docker/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=qqhzn.000 \
-d mysql:5.7.22


-p 3308:3306:将容器的3306端口映射到主机的3308端口
-v /usr/local/docker/mysql/conf:/etc/mysql:将主机当前目录下的 conf 挂载到容器的 /etc/mysql
-v /usr/local/docker/mysql/logs:/var/log/mysql:将主机当前目录下的 logs 目录挂载到容器的 /var/log/mysql
-v /usr/local/docker/mysql/data:/var/lib/mysql:将主机当前目录下的 data 目录挂载到容器的 /var/lib/mysql
-e MYSQL\_ROOT\_PASSWORD=123456:初始化root用户的密码
  • 使用数据卷配置MySQL容器最大能导入的sql语句

    • 在启动容器内配置
    //首先启动一个MySQL容器
    docker run -p 3308:3306 --name mysql \
    -v /usr/local/docker/mysql/logs:/var/log/mysql \
    -v /usr/local/docker/mysql/data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=qqhzn.000 \
    -d mysql:5.7.22
    
    //进入这个启动的容器中
    [email protected]:/usr/local/docker/mysql# docker exec -it  mysql bash
    
    //查询MySQL配置文件的位置
    [email protected]:/# whereis mysql
    mysql: /usr/bin/mysql /usr/lib/mysql /etc/mysql /usr/share/mysql
    
    //查询配置
    [email protected]:/# cd /etc/mysql
    [email protected]:/etc/mysql# cd conf.d/
    [email protected]:/etc/mysql/conf.d# cat mysqldump.cnf 
    [mysqldump]
    quick
    quote-names
    max_allowed_packet	= 16M
    
    //将`max_allowed_packet`的配置追加到mysqld.cnf末尾中
    [email protected]:/etc/mysql/mysql.conf.d# echo "max_allowed_packet = 128M" >> mysqld.cnf
    
    
    • 上面配置是临时的修改,当容器销毁后,有需要重新配置,因此要将容器中的配置复制放到宿主机,作用于新容器
    //将容器里的配置文件拷贝入宿主机
    [email protected]:/usr/local/docker/mysql/conf# docker cp mysql:/etc/mysql .
    
    //将复制文件内的文件移动到上级目录
    [email protected]:/usr/local/docker/mysql/conf/mysql# mv *.* ..
    [email protected]:/usr/local/docker/mysql/conf# rm -rf mysql/
    
    //删掉原有的容器
    [email protected]:/usr/local/docker/mysql/conf# docker rm -f mysql
    //删掉挂载的数据文件
    [email protected]:/usr/local/docker/mysql# rm -rf data/
    
    //新建数据库并挂在数据卷
    [email protected]:/usr/local/docker/mysql# docker run -p 3308:3306 --name mysql \
    -v /usr/local/docker/mysql/conf:/etc/mysql \
    -v /usr/local/docker/mysql/logs:/var/log/mysql \
    -v /usr/local/docker/mysql/data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=qqhzn.000 \
    -d mysql:5.7.22
    
    

项目的容器化部署

  • 先初始化数据库数据
  • 再用数据卷导入已经解压的目录
[email protected]:/usr/local/docker/tomcat/ROOT# ll
total 20
drwxr-xr-x 5 root root 4096 Mar 17 17:57 ./
drwxr-xr-x 3 root root 4096 Mar 17 14:01 ../
drwxr-xr-x 2 root root 4096 Mar 17 10:05 META-INF/
drwxr-xr-x 4 root root 4096 Mar 17 10:05 static/
drwxr-xr-x 7 root root 4096 Mar 17 10:05 WEB-INF/

[email protected]:/usr/local/docker/tomcat# docker run -p 8088:8080 --name myshoptomcat -d \
>  -v /usr/local/docker/tomcat/ROOT:/usr/local/tomcat/webapps/ROOT tomcat:8-jre8
  • 记得修改数据源,并且要先启动MySQL再启动Tomcat
  • 查看tomcat日志
docker logs myshoptomcat

//一直监听者日志的变化
docker logs -f  myshoptomcat

Docker Compose

  • 解决部署多个容器的复杂启动参数,和容器的管理

Compose 中有两个重要的概念:

  • 服务 (service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
  • 项目 (project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。

安装

Docker Compose 存放在Git Hub,不太稳定。你可以也通过执行下面的命令,高速安装Docker Compose。

curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

使用

docker-compose.yml

编写 docker-compose.yml 文件,这个是 Compose 使用的主模板文件。

(不能用 Tab)

caversion: '3'
services:
  tomcat:
    restart: always
    image: tomcat:8-jre8
    container_name: mytomcat
    ports:
      - 8088:8080

运行 compose 项目

[email protected]:/usr/local/docker/tomcat# docker-compose up

//守护态
[email protected]:/usr/local/docker/tomcat# docker-compose up -d

此时访问本地 8088 端口即可

命令说明

模板文件

docker-compose部署项目

version: '3'
services:
  web:
    restart: always
    image: tomcat:8-jre8
    container_name: myshoptomcat
    ports:
      - 8088:8080
    volumes:
      - /usr/local/docker/myshop/ROOT:/usr/local/tomcat/webapps/ROOT

  mysql:
    restart: always
    image: mysql:5.7.22
    container_name: myshopmysql
    ports:
      - 3308:3306
    environment:
      TZ: Asia/Shanghai
      MYSQL_ROOT_PASSWORD: 123456
    command:
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
      --explicit_defaults_for_timestamp=true
      --lower_case_table_names=1
      --max_allowed_packet=128M
      --sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:
  • 导入数据库
  • 解压项目压缩包到ROOT目录下,修改数据源
  • 重启docker-compose
docker-compose up

docker-compose down