Docker使用小结

319 阅读23分钟

安装

  • 使用阿里云中的方法安装(推荐

  • 登录阿里云,点击右上角的控制台,依次点击:1. 左上角图标---->2. 产品与服务---->3. 容器镜像服务

  • 接着:1. 点击镜像加速器---->2. 选择系统类型---->3. 点击docker-ce链接跳转(按照页面所述步骤安装即可)---->4. 安装完成后配置镜像加速器步骤

  • 通过 docker 官网文档中的方法安装

  • 打开 docs.docker.com,选择系统类型,根据步骤安装

配置镜像加速器

参照上一节的“使用阿里云中的方法安装”

CentOS7启动Docker命令

  • 启动/重启/停止/查看状态:systemctl start/restart/stop/status docker

  • 重新加载配置文件:systemctl reload docker,然后重启(配置文件/etc/docker/daemon.json)

  • 开启/关闭开机自启动:systemctl enable/disable docker

docker命令格式

  • docker [OPTIONS] COMMAND

帮助命令

  • docker [COMMAND] --help: 帮助命令,及其详细,不知道怎么使用命令,就看它的帮助命令

  • docker version: docker相应的版本信息

  • docker info: 显示 Docker 系统信息,包括镜像和容器数

镜像

  • UnionFS(联合文件系统):是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual file system)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

  • Docker镜像加载原理:docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统即UnionFS,主要包含两个:

  • bootfs(boot file system)主要包含bootLoader和kernel,bootLoader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

  • rootfs(root file system)在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如CentOS,Ubuntu等,docker中的CentOS能做到只有200M,就是因为rootfs及精简,只包含基本的内容(bootfs是通用的,CentOS、Ubuntu等用的都是一样的boofs)。

  • 分层的镜像:当pull一个镜像时,会发现下载不止一个镜像。比如一个tomcat近500M,kernel-->centos-->jdk8-->tomcat(不全面),所以会这么大。

  • 为什么Docker镜像要采用分层结构?最大的好处就是:共享资源。比如有多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保存一份base镜像,同时内存中也只需要加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

  • 特点:Docker镜像都是只读的。当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

镜像命令

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

  • docker images [OPTIONS]: 列出本地镜像

  • -a: 列出本地所以镜像(含中间映像层)

  • -q: 只显示镜像ID

  • --digests: 显示镜像的摘要信息

  • --no-trunc: 显示完整的镜像描述

  • docker search [OPTIONS] 镜像名称: 去docker hub上查找(配置镜像加速器仅仅是从那边拉数据,但是查找还是在docker hub上hub.docker.com

  • --no-trunc: 显示完整的镜像描述

  • -s number: 列出收藏数不小于指定值的镜像

  • --automated: 只列出automated build类型的镜像

  • docker pull 镜像名称[:TAG]: 下载镜像到本地,若无版本,则默认latest

  • docker rmi [OPTIONS] 镜像名称[:TAG]/镜像ID: 删除镜像,删除多个则以空格隔开

  • -f: 强制删除镜像,不管有没有container正在运行

  • docker rmi -f (dockerimagesqa):清空镜像,(docker images -qa): 清空镜像,()也可用``代替

  • docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]: 提交容器副本使之成为一个新的镜像

容器命令

docker 利用容器 container 独立运行一个或一组应用。容器是用镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看作是一个简易版的 Linux 环境(包括 root 用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

  • docker run [OPTIONS] image [COMMAND] [ARG...]: 根据镜像运行容器

  • --name="容器新名字": 为容器指定一个名称

  • -d: 后台运行容器,并返回容器ID,也即启动守护式容器

  • 以此方法运行的容器,使用docker ps -a进行查看,会发现容器已经退出

  • docker容器后台运行,就必须有一个前台进程

  • 容器运行的命令如果不是那些一直挂起的命令(如top,tail),是会自动退出的,因为他认为他无事可做了。这是docker的运行机制

  • docker run -d centos /bin/sh -c "while true;do echo hello zzyy;sleep 2;done": 此命令是让centos后台进程每隔2秒不断打印hello zzyy,因此此命令运行的容器实例不会自动退出,然后可用下方的后台进程日志打印查看日志(docker logs)

  • -i: 以交互模式运行容器,也即启动交互式容器,通常与 -t 同时使用

  • -t: 为容器重新分配一个伪输入终端(类似CentOS的终端),通常与 -i 同时使用

  • -P: 随机端口映射

  • -p: 指定端口映射,有以下四种格式,containerPort就相当于tomcat默认的8080,hostPort就是对外的访问端口

  • ip:hostPort:containerPort

  • ip::containerPort

  • hostPort:containerPort

  • containerPort:不写hostPort,则随机分配

  • docker create: 创建一个新的容器,通run,但不启动容器

  • docker ps [OPTIONS]: 列出正在运行的容器实例

  • -a: 列出当前所有正在运行的容器实例+历史上运行过的

  • -l: 显示最近创建的容器

  • -n: 显示最近n个创建的容器

  • -q: 静默模式,只显示容器ID

  • --no-trunc: 不截断输出

  • 退出正在运行的容器,有两种方式:

  • exit: 容器停止退出

  • ctrl+P+Q: 容器不停止退出,可用docker attach重新进入

  • docker start 容器ID/容器名称: 启动容器

  • docker restart 容器ID/容器名称: 重启容器

  • docker stop 容器ID/容器名称: 停止容器

  • docker kill 容器ID/容器名称: 强制停止容器

  • docker pause 容器ID: 暂停容器

  • docker unpause 容器ID: 取消暂停容器

  • docker rename: 重命名容器

  • docker rm [OPTIONS] 容器ID/容器名称: 删除停止的容器

  • -f: 强制删除,不管有没有运行

  • docker rm -f (dockerpsqa):删除所有容器,(docker ps -qa): 删除所有容器,()也可用``代替

  • docker ps -qa | xargs docker rm: 删除所有容器

  • docker logs -f -t --tail number 容器ID: 查看容器日志

  • -t: 加入时间戳

  • -f: 跟随最新的日志打印

  • --tail number: 显示最后多少条

  • docker top 容器ID: 查看容器内运行的进程

  • docker inspect 容器ID: 以json字符串的形式查看容器内部细节

  • 进入正在运行的容器并以命令行交互

  • docker attach 容器ID: 重新进入终端,直接进入容器启动命令的终端,不会启动新的进程

  • docker exec -it 容器ID bashShell: 不显示终端执行,是在容器中打开新的终端,并且可以启动新的进程,bashShell是命令

  • docker exec -t 容器ID /bin/bash: 和attach一样效果,但打开新终端,并且exit无法关闭容器,容器仍在运行

  • docker cp 容器ID:容器内路径 目的主机路径: 从容器拷贝文件到主机上

其他命令

  • diff: 查看容器的变化

  • events: 从docker服务获取容器实时事件

  • export: 导出容器的内容流作为一个tar归档文件(对应import)

  • import: 从tar包中的内容创建一个新的文件系统映像(对应export)

  • docker load -i target.tar: 从一个tar包中加载一个镜像(对应save)

  • docker save -o source.tar 镜像ID: 保存一个镜像为一个tar包(对应load)

  • login: 注册或登录一个docker源服务器

  • logout: 从当前Docker registry退出

  • port: 查看映射端口对应的容器内部源端口

  • wait: 截取容器停止时的退出状态值

  • stats: 实时展示容器资源使用情况

  • update: 更新容器配置

Docker容器数据卷

  • 将应用于运行的环境打包形成容器运行,但是我们对数据的要求希望是持久化的。容器之间希望有可能共享数据。Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后(不运行即删除),数据自然也就没有了。为了能保存数据,在docker中使用卷。

  • 卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性。卷的设计目的就是数据的持久化,完全独立于容器的生命周期,因此Docker不会在容器删除时删除其挂载的数据卷。

  • 特点:数据卷可在容器之间共享或重用数据;卷中的更改可以直接生效;数据卷中的更改不会包含在镜像的更新中;数据卷的生命周期一直持续到没有容器使用它为止。

  • docker run -it -v 宿主机绝对路径目录:容器内绝对路径目录[:ro] image: 绑定宿主机的目录与容器内的目录

  • 若目录不存在,会自动创建目录;

  • 在后面加上:ro(readonly),那么容器只能查看,不能增删改;

  • 这种方式只能绑定一个宿主机目录(若要绑定多个,接着空格 -v ...即可),使用DockerFile可以绑定多个;

  • 如果访问目录出现cannot open directory .: Permission denied,在镜像名称前加--privileged=true即可。

  • DockerFile是image模板的描述文件,有自己的语法规则,新建一个文件,编辑内容:

    FROM centos VOLUME ["/volumeData1","/volumeData2","/volumeData3"] CMD echo "success" CMD /bin/bash

  • 然后使用docker build -f 文件绝对路径 -t 镜像名称[:TAG] .,生成image,再运行一个容器docker run -it 镜像名称。可观察到有上面三个容器卷目录。

  • 使用docker inspect 容器ID,可发现docker会自动绑定宿主机的目录。

  • docker build -f 文件绝对路径 -t 镜像名称[:TAG] .: 将DockerFile文件变成镜像,最后一个英文句号不能少,表示当前路径,使用DockerFile中的VOLUME指令绑定的容器卷,可使用docker inspect 容器ID查看绑定的对应宿主机目录。

  • 数据卷容器:命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,此容器称为数据卷容器。容器间传递共享--volumes-from,实例如下:

  • 借用上方生成的镜像(含三个数据卷),先启动一个父容器docker run -it --name dcf mycentos,发现当前容器内目录含三个数据卷目录,在其中一个目录创建文件;

  • docker run -it --name dcs01 --volumes-from dcf mycentos,发现三个数据卷目录,在目录下可发现dcf创建的文件,创建一个文件;

  • docker run -it --name dcs02 --volumes-from dcf mycentos,发现三个数据卷目录,在目录下可发现dcf和dcs01创建的文件,创建一个文件;

  • 重新查看dcf目录,会发现有三个文件,说明父到子、子到父、子到子数据都可以共享;

  • 终止dcf,再查看dcs01中数据卷目录,会发现文件仍在,创建一个新文件,再查看dcs02中数据卷目录,会发现旧文件和dcs01创建的新文件都在,说明容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。其实使用docker inspect命令查看三个容器的数据卷信息,会发现三个容器都绑定的宿主机某个目录。

DockerFile

  • DockerFile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本

  • 构建三步骤:编写DockerFile文件---->docker build---->docker run

  • docker基础镜像scratch,类似Java中的Object

  • 构建过程解析:

  • DockerFile内容基础知识

  • 每条保留字指令都必须为大写字母且后面要跟随至少一个参数

  • 指令按照从上到下,顺序执行

  • #表示注释

  • 每条指令都会创建一个新的镜像层,并对镜像进行提交

  • docker执行DockerFile的大致流程

  • docker从一个基础镜像运行一个容器(最基础的镜像scratch,类似Java中的Object)

  • 执行一条指令并对容器做出修改

  • 执行类似docker commit的操作提交一个新的镜像层

  • docker再基于刚提交的镜像运行一个新容器

  • 执行dockerfile中的下一条指令(即重复步骤234)直到所有指令都执行完成

  • 总结

  • 从应用软件的角度来看,DockerFile、Docker镜像和Docker容器分别代表软件的三个不同阶段

  • DockerFile是软件的原材料,定义了进程需要的一切东西,包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这是需要考虑如何设计namespace的权限控制)等等

  • Docker镜像是软件的交付品

  • Docker容器则可以认为是软件的运行态,是直接提供服务的

  • DockerFile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署和运维,三者缺一不可,合力充当Docker体系的基石

  • DockerFile体系结构(保留字指令)

  • FROM: 基础镜像,当前新镜像是基于哪个镜像的

  • MAINTAINER: 镜像维护者的姓名和邮箱地址

  • RUN: 容器构建时需要运行的命令

  • EXPOSE: 当前容器对外暴露的端口

  • WORKDIR: 指定在创建容器后,终端默认登录的进来工作目录

  • ENV: 用来在构建镜像过程中设置环境变量

  • ENV MY_PATH /usr/mytest这个环境变量可以在后续的任何RUN指令中使用,这个就如同在命令前面指定了环境变量前缀一样

  • 也可以在其他指令中直接使用这些环境变量

  • 比如:WORKDIR $MY_PATH

  • ADD: 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包

  • COPY: 拷贝文件和目录到镜像中

  • COPY src dest

  • COPY ["src","dest"]

  • VOLUME: 容器数据卷,用于数据保存和持久化工作

  • CMD: 指定一个容器启动时要运行的命令,DockerFile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

  • shell格式:CMD <命令>

  • exec格式:CMD ["可执行文件","参数1","参数2"...]

  • 参数列表格式:CMD ["参数1","参数2"...],在指定了ENTRYPOINT指令后,用CMD指定具体的参数

  • ENTRYPOINT: 指定一个容器启动时要运行的命令,ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数

  • ONBUILD: 父镜像在被子继承后,父镜像的ONBUILD被触发(构建时就触发,FROM运行之后)

  • 自定义CentOS

  • 初始的CentOS运行时默认路径是/;默认不支持vim;默认不支持ifconfig

  • 自定义MyCentOS,使其具备登录后的默认路径;vim编辑器;查看网络配置ifconfig

    FROM centos MAINTAINER Mr.Chan2643494730@qq.com ENV mypath /usr/local WORKDIR $mypath EXPOSE 80 RUN yum -y install vim RUN yum -y install net-tools CMD /bin/bash

  • 运行pwd、vim、ifconfig会发现自定义成功

  • docker history 容器ID: 查看镜像的变更历史

  • CMD和ENTRYPOINT区别

  • CMD只执行最后一条,tomcat为什么一启动就运行,因为最后这一句CMD ["catalina.sh", "run"],如果在docker run后面加命令(docker run -it -p 7777:8080 tomcat ls -l),那么CMD ["catalina.sh", "run"]就不会执行,只会执行ls -l,tomcat也就没有运行

  • ENTRYPOINT不同,docker run 之后的参数会被当做参数传递给ENTRYPOINT(追加),之后形成新的命令组合

  • CMD和ENTRYPOINT都存在时,CMD的指令变成了ENTRYPOINT的参数,并且此CMD提供的参数会被 docker run 后面的命令覆盖

  • 自定义tomcat

  • mkdir -p /zzyyuse/mydockerfile/tomcat9

  • 在上述目录下touch c.txt

  • 将jdk和tomcat安装的压缩包拷贝进上一步目录

  • cp /root/apache-tomcat-9.0.29.tar.gz .

  • cp /root/jdk-8u144-linux-x64.tar.gz .

  • 在/zzyyuse/mydockerfile/tomcat9目录下新建DockerFile文件,内容如下

    FROM centos MAINTAINER chanchan199513@163.com #把宿主机当前目录的c.txt文件拷贝到容器/usr/local路径下 COPY c.txt /usr/local/cincontainer.txt #把jdk和tomcat添加到容器中 ADD jdk-8u144-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.29.tar.gz /usr/local/ #安装vim编辑器 RUN yum -y install vim #设置工作访问时候的路径 ENV MYPATH /usr/local WORKDIR MYPATH #配置jdk与tomcat环境变量 ENV JAVA_HOME /usr/local/jdk1.8.0_144 ENV CLASSPATH JAVA_HOME/lib/dt.jar:JAVAHOME/lib/tools.jarENVCATALINAHOME/usr/local/apachetomcat9.0.29ENVCATALINABASE/usr/local/apachetomcat9.0.29ENVPATHJAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.29 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.29 ENV PATH PATH:JAVAHOME/bin:JAVA_HOME/bin:CATALINA_HOME/lib:$CATALINA_HOME/bin #容器运行时监听的端口 EXPOSE 8080 #启动时运行tomcat

    ENTRYPOINT ["/usr/local/apache-tomcat-9.0.29/bin/startup.sh"]

    CMD ["/usr/local/apache-tomcat-9.0.29/bin/catalina.sh","run"]

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

  • 构建:docker build -f DockerFile -t tomcat9 .

  • 运行,两个数据卷是为了查看tomcat测试以及日志

    docker run -d -p 9080:8080 --name myt9
    -v /zzyyuse/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.29/webapps/test -v /zzyyuse/mydockerfile/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.29/logs --privileged=true tomcat9

  • 查看验证

  • docker exec -t myt9 cd apache-tomcat-9.0.29/logs && ls -l: 看容器内日志目录中的文件

  • docker exec -t myt9 pwd看工作目录

  • docker exec -t myt9 ls -l看文件有没有拷贝到容器内

  • 使用Firefox访问127.0.0.1:9080,看tomcat有没有启动成功

  • 可以在test文件夹下写个jsp测试

常用安装

  • 总体步骤

  • 搜索镜像

  • 拉取镜像

  • 查看镜像

  • 启动镜像

  • 停止容器

  • 移除容器

  • 安装tomcat

  • docker hub上面查找tomcat镜像----docker search tomcat

  • 从docker hub上拉取tomcat镜像到本地----docker pull tomcat

  • 查看是否拉取到tomcat----docker images

  • 使用tomcat镜像创建容器(也叫运行镜像)----docker run -it -p 9080:8080 tomcat

  • 安装MySQL

  • docker hub上面查找mysql镜像----docker search mysql

  • 从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.6----docker pull mysql:5.6

  • 使用mysql5.6镜像创建容器----docker run -p 12345:3306 --name mysql -v /zzyyuse/mysql/conf:/etc/mysql/conf.d -v /zzyyuse/mysql/logs:/logs -v /zzyyuse/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6

  • docker run -p 12345:3306    端口映射

  • --name mysql    命名容器

  • -v /zzyyuse/mysql/conf:/etc/mysql/conf.d    mysql配置

  • -v /zzyyuse/mysql/logs:/logs    mysql日志

  • -v /zzyyuse/mysql/data:/var/lib/mysql    mysql数据

  • -e MYSQL_ROOT_PASSWORD=123456     root用户密码

  • -d mysql:5.6    后台运行

  • 容器正在运行----docker ps

  • 进入容器----docker exec -it 容器ID /bin/bash

  • 使用root用户登录mysql----mysql -uroot -p 回车然后输入密码123456

  • 建库,建表等等

  • create database db01;

  • use db01;

  • create table t_boot(id int not null primary key,bookname varchar(20));

  • show tables;

  • 数据备份(使用docker)----docker exec mysql容器ID sh -c 'exec mysqldump --all-databases -uroot -p"123456"' > /zzyyuse/all-database.sql

  • 安装Redis

  • 从docker hub上(阿里云加速器)拉取redis镜像到本地,标签为3.2----docker pull redis:3.2

  • 创建容器----docker run -p 6379:6379 -v /zzyyuse/myredis/data:/data -v /zzyyuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes

  • docker run -p 6379:6379 端口映射

  • -v /zzyyuse/myredis/data:/data redis数据

  • -v /zzyyuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf redis配置(这个不是文件,是文件夹)

  • -d redis:3.2 后台运行

  • redis-server /usr/local/etc/redis/redis.conf --appendonly yes CMD命令(--appendonly yes开启aof,数据持久化)

  • 在主机/zzyyuse/myredis/conf/redis.conf目录下新建redis.conf文件----vim /zzyyuse/myredis/conf/redis.conf/redis.conf,将redis的配置文件复制到此文件中(需将bind注释掉,因为没有绑死这种说法)

  • 连接redis----docker exec -it redis服务容器ID redis-cli

  • 添加数据set k1 v1

  • 测试持久化文件生成---- cat /zzyyuse/myredis/data/appendonly.aof

本地镜像发布到阿里云

  • 镜像的生成方法

  • 使用DockerFile

  • 从容器创建一个新的镜像----docker commit [OPTIONS] 容器ID REPOSITORY[:TAG]

  • 将本地镜像推送到阿里云

  • 准备本地镜像素材原型

  • 阿里云开发者平台,登录后选择容器镜像服务

  • 创建命名空间

  • 创建镜像仓库

  • 点击创建的仓库右侧的管理按钮

  • 新页面会有将镜像推送到Registry的说明

  • 第一步登录阿里云Docker Registry:$ sudo docker login --username=XXX registry.cn-hangzhou.aliyuncs.com

  • 第二步标注将上传镜像的版本信息:$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/xxx/my-images:[镜像版本号]

  • 第三步推送镜像至阿里云容器镜像服务:$ sudo docker push registry.cn-hangzhou.aliyuncs.com/xxx/my-images:[镜像版本号]

  • 将阿里云上的镜像下载到本地

  • $ sudo docker pull registry.cn-hangzhou.aliyuncs.com/xxx/my-images:[镜像版本号]

  • 搜索:命名空间/镜像仓库:TAG

构建私有仓库

  • 启动Docker Registry,使用Docker官方提供的Registry镜像就可以搭建本地私有镜像仓库,具体指令如下:

    docker run -d -p 5000:5000 --restart=always --name registry
    -v /mnt/registry:/var/lib/registry registry:2

  • 标注镜像版本信息:docker tag hello-world:latest localhost:5000/my-hello-world

  • 推送镜像(不需要登录,不安全):docker push localhost:5000/my-hello-world

  • 查看本地仓库镜像:http://localhost:5000/v2/my-hello-world/tags/list

  • 可在/mnt/registry目录中查看

  • 配置私有仓库认证

  • 查看Docker Registry(以下简称DR)所在服务器地址ifconfig

  • 生成自签名证书(在home目录下执行下面的指令)。要确保DR的安全性,还需要一个安全认证证书来保证其他Docker机器不能随意访问DR,所以要在DR的Docker主机上生成自签名证书(如果已购买证书就无需生成),具体操作指令如下

    mkdir registry && cd registry && mkdir certs
    && cd certs openssl req -x509 -days 3650 -subj '/CN=ip:port/' -nodes
    -newkey rsa:2048 -keyout domain.key -out domain.crt

  • 说明:-x509是一个自签发证书的格式,-days 3650表示证书有效期,ip:port表示DR的地址,rsa:2048是证书的算法长度,domain.key和domain.crt就是生成的证书文件

  • 生成用户名和密码

    cd .. && mkdir auth docker run --entrypoint htpasswd registry:2 -Bbn 账号 密码 > auth/htpasswd

  • 启动DR

    docker run -d -p 5000:5000 --restart=always --name registry
    -v /mnt/registry:/var/lib/registry -v pwd/auth:/auth
    -e "REGISTRY_AUTH=htpasswd"
    -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
    -v pwd/certs:/certs
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt
    -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key
    registry:2

  • 配置DR访问接口

    mkdir -p /etc/docker/certs.d/ip:port cp certs/domain.crt /etc/docker/certs.d/ip:port

  • DR私有仓库使用登记

  • 编辑daemon.json文件vim /etc/docker/daemon.json

  • 添加{"insecure-registries":["ip:port"]}

  • 重启并加载docker配置文件

  • systemctl reload docker

  • systemctl restart docker

Docker网络管理

虽然Docker提供的默认网络的使用比较简单,但是为了保证各容器中应用的安全性,在实际开发中更推荐使用自定义的网络进行容器管理。在Docker中,可以自定义bridge网络、overlay网络,也可以创建network plugin(网络插件)或者远程网络以实现容器网络的完全定制和控制。

  • Bridge networks(桥接网络,默认网络):基于bridge驱动的自定义网络可以较好的实现容器隔离。适合单主机的小型网络环境管理,但对于大型的网络环境管理(如集群)就需要考虑使用自定义overlay集群。

  • docker network create --driver bridge isolated_nw: 创建一个基于bridge驱动名称为isolated_nw的网络,--driver可换-d,--driver bridge可省略,docker默认bridge

  • docker run -itd --name=nwtest --network=isolated_nw busybox: 指定网络

  • docker inspect nwtest: 查看网络配置

  • docker network connect bridge nwtest: 给容器添加一个新的网络

  • docker network disconnect isolated_nw nwtest: 断开容器的网络

  • docker network rm isolated_nw: 移除名称为isolated_nw的自定义网络

  • docker network ls: 查看网络

  • Overlay network in swarm mode(Swarm集群中的覆盖网络):为了保证安全性,Swarm集群使自定义的overlay网络只适用于需要服务的集群中的节点,而不会对外部其他服务或者Docker主机开放。

  • Custom network plugins(定制网络插件):若前几种自定义网络都无法满足需求,可以使用Docker提供的插件来自定义网络驱动插件。自定义网络插件会在Docker进程所在主机上作为另一个运行的进程。自定义网络驱动插件与其他插件遵循相同的限制和安装规则,所有插件都使用Docker提供的插件API,并且会有一个包含安装、启动、停止和激活的生命周期。

  • 容器间的网络通信

  • 查看网络使用情况:docker network inspect 网络名称

  • 创建两个使用默认的bridge网络的容器

    docker run -itd --name=c1 busybox docker run -itd --name=c2 busybox

  • 创建一个使用自定义的isolated_nw网络的容器

    docker network create --driver bridge isolated_nw docker run -itd --network=isolated_nw --name=c3 busybox

  • 为container2容器新增一个自定义的isolated_nw网络连接

    docker network connect isolated_nw c2

  • 查看c1,c2,c3之间能不能相互通信:ping -w 4 ip

  • 很明显c1和c2,c2和c3是可以通信的,c1和c3不能通信(c1同样不能ping通c2的172.18.0.3)

搭建Docker Swarm集群

通过把多个Docker Engine聚集在一起,形成一个大的docker-engine,对外提供容器的集群服务。同时这个集群对外提供Swarm API(和docker 的命令基本一样),用户可以像使用Docker Engine一样使用Docker集群。Swarm daemon只是一个调度器(Scheduler)加路由器(router),Swarm自己不运行容器,只是接受docker客户端发送过来的请求,调度合适的节点来运行容器,这意味着即使Swarm由于某些原因挂掉了,集群中的节点也会照常运行,当Swarm重新恢复运行之后,它会收集重建集群信息。

  • docker swarm特点

  • 对外以Docker API接口呈现

  • Swarm本身专注于Docker集群管理,非常轻量,占用资源少

  • Swarm目前与Docker同步发布

  • 架构

  • 集群搭建步骤

2.1命令执行之后,daemon会给出节点如何加入swarm集群的命令,复制执行 管理节点中的docker也是会运行容器的,Swarm daemon不运行容器

加入不了的,关闭防火墙systemctl stop firewalld

Docker Compose服务编排

  • 一个项目的完整环境包括应用节点(app)、数据库(MySQL)、缓存(Redis)。为了管理方便,是否可以将这些节点全部构建在一个容器中运行?答案是可以的,但并不推荐者这么做,因为它违背了Docker中运行环境隔离的设计初衷(每个节点都有其运行环境,如果合在一起,自然它们的环境也要搓合在一起)。而且微服务架构中服务的数量很多,不可能一个一个的用命令启动。

  • 那么怎么简化多节点项目环境的维护呢?Docker-compose就可以解决该问题。通过DockerCompose.yml描述项目中各节点容器信息,以及依赖信息。然后通过docker -compose一键构建或启动。docker-compose.yml示例文件:

    version: '3.3' compose的版本 services: 项目 nginx: 项目的下一级代表应用,此处是nginx应用(容器名称) image: nginx[:TAG] 镜像名称 ports: 端口映射,与-p一样 - "80:80" links: 链接到app容器(nginx做反向代理需要知道服务的ip及port,如果没有这个链接,那么需要写死,显然不合适,所以有了links) - app volumes: 目录挂载 - "./nginx.conf.d/:/etc/nginx/conf.d/" app: image: luban/app

  • 安装docker-compose

  • 查看compose版本github.com/docker/comp…

  • 下载软件(Compose是依赖于Docker引擎的,要先安装Docker):curl -L github.com/docker/comp… -s`-`uname -m` -o /usr/local/bin/docker-compose

  • 赋予执行权限:chmod +x /usr/local/bin/docker-compose

  • 检测安装情况:docker-compose -v

  • 可以创建软链接,缩短命令,如dc代替docker-compose:ln -s 文件名称 软链接名称(ln -s docker-compose dc)

  • 卸载docker compose: rm /usr/local/bin/docker-compose

  • 服务编排步骤:分为三步(在创建的一个空目录下执行)

  • 编写DockerFile文件(为每个服务构建需要的镜像,方便迁移----不是必须的)

  • 编写docker-compose.yml文件(编写部署服务相关指令)

  • 运行docker-compose up(启动yml文件中的服务)

  • 示例

  • 准备:两个镜像(未通过DockerFile构建)

    docker pull mysql:5.7 docker pull wordpress

  • 新建一个空白目录,新建一个docker-compose.yml文件,编辑该文件:

    version: '3' services: db: image: mysql:5.7 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: wordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on: - db image: wordpress:latest ports: - "8001:80" restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress volumes: db_data:

该文件中的内容,新建db和wordpress容器,等同于:

docker run --name db -e MYSQL_ROOT_PASSWORD=123456 -d mysql
docker run --name some-wordpress --link db:mysql -p 8001:80 -d wordpress

Docker可视化界面:Portainer

Docker可视化常用工具:docker UI (只能连接本地服务器),shipyard (已停止维护),portainer,daocloud (收费)

  • Portainer是Docker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管理的全部需求。

  • 下载Portainer镜像

  • 查询docker search portainer

  • docker pull portainer/portainer

  • 单机版运行----仅有一个docker宿主机时

    docker run -d -p 9000:9000 端口映射 --restart=always 开机启动 -v /var/run/docker.sock:/var/run/docker.sock 容器卷 --name portainer-test 命名 portainer/portainer

单机版选择local即可

  • 集群运行

  • 在有多台Docker的情况下,进行集群管理就十分重要了,Portainer也支持集群管理,Portainer可以和Swarm一起来进行集群管理操作,Swarm搭建参考上文。

    docker run -d -p 9000:9000 --restart=always --name portainer-test portainer/portainer

集群运行选择Remote,输入swarm的ip,然后点击Connect。登录成功之后如下

可以在Endpoints中新增Docker节点

然后通过如下方式进行切换节点,双击,就可以切换节点,进行管理。

  • 首次登陆需要注册用户,给admin用户设置密码(portainer)