Docker学习笔记
文章目录
- Docker学习笔记
- 基础概念
- Docker 安装
- Docker 常用命令
- 构建私有镜像
- Docker运行java程序
- 使用docker搭建weblogic环境
- 构建docker私有仓库
- 数据挂载
- Compose集成式应用组合
- 简介
- 安装和卸载
- 案列 Compose构建dubbo-admin服务
- compose命令说明
- docker-compose build
- docker-compose config
- docker-compose down
- docker-compose exec
- docker-compose images
- docker-compose kill
- docker-compose logs
- docker-compose pause
- docker-compose port
- docker-compose ps
- docker-compose pull
- docker-compose push
- docker-compose restart
- docker-compose rm
- docker-compose run
- docker-compose scale
- docker-compose start
- docker-compose stop
- docker-compose top
- docker-compose unpause
- docker-compose up
- docker-compose version
- Docker监控
- 快速扩容
基础概念
Docker是使用Google推出的go语言开发实现的,基于Linux内核的cgroup,namespace,等技术对线程进行了封装隔离,属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其他隔离的进程,因此也称之为容器。
Docker在容器的基础上,进行了进一步的封装,从文件系统,网络互联到进程隔离等等,极大的简化了容器的创建和维护。使Docker技术比虚拟机技术更为轻便,快捷。
Docker与传统虚拟机技术
传统虚拟机技术:是虚拟出一套硬件设备后,在其上边运行一个完整操作系统,在该系统上再运行所需要的的应用进程。
Docker:容器内的应用进程直接运行与宿主的内核,容器没有自己的内核,而且也没有进行硬件虚拟。所以容器比传统虚拟机更轻便。
对比传统虚拟机总结
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为MB | 一般为GB |
性能 | 接近原生 | 较差 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
Docker优点
- 可以更高效的利用系统资源。
- 拥有更快速的启动时间。
- 一致的运行环境。
- 持续交付和部署。
- 更轻松的迁移。
- 更轻松的维护和扩展。
Docker架构
Docker使用客户端-服务端(c/s)架构模式,使用远程API来管理和创建Docker容器。
Docker镜像是docker容器的一个模板,是独立运行的一个或者一组应用。客户端通过命令行获取其他的工具,使用dockerAPI 和docker的守护进程进行通信。
三个基本概念
Docker Registry > 仓库 > 镜像 > 容器
一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
镜像(Image)
Docker镜像相当于是一个root文件系统,Docker是一个特殊的文件系统,除了提供容器运行时所需要的的程序、库、资源、配置等文件外,还包含了一些为运行准备的一些配置参数(如环境变量)。镜像不包含任何动态数据,其内容在构建后也不会被改变。
Docker镜像分层存储
因为镜像包含操作系统完整的root文件系统,其体积很庞大。因此Docker在设计时将其设计为分层存储的架构。镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成。或者可以理解为由多层文件系统联合组成。
镜像在构建时,会一层层构建,前一层是后一层的基础。每一层构建完毕后不会再改变,后一层的任何改变只会发生在自己这一层,在构建镜像时需要额外的小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
分层存储的特征使镜像的复用、定制变得更加容易。甚至可以使用之前构建好的镜像作为基础层,然后进一步添加新的的层,以定制自己所需的东西,构建新的镜像。
容器(Container)
镜像和容器的关系可以看做是 java 中类和实例的关系。镜像时静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
镜像使用的是分层存储,容器也是一样的。每一个容器运行时是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个容器运行时读写而准备存储层为容器存储层。
容器存储层的生命周期和容器一样,容器消亡时,容器存储层也会消失。因此任何保存于容器存储层的信息都会随着容器的删除而丢失。
按照Docker最佳实践的要求,容器不应该向存储层内写任何数据,容器存储层要保持无状态化。所有文件的写入操作都应该使用volume 数据卷、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或者网络存储)发生读写,其性能和稳定性更高。
数据卷的生命周期独立于容器,容器消亡,数据卷不会消亡。因此使用数据卷之后,容器删除或者重新运行之后数据不会丢失。
仓库(Repository)
镜像构建完成后可以很容易的在当前宿主机上运行。但是如果需要在其他服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过
<仓库名>:<标签> 的格式来具体指定是哪个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。
Docker Registry 公开仓库 官方Docker Hub 也是默认的Registry。
Docker Registry 私有仓库 Docker Registry 镜像可以直接使用作为私有Registry服务。
Docker 安装
Docker版本命名
同时Docker划分为CE 和 EE ,CE即社区版(免费支持周期三个月)EE即企业版,安全,收费使用。
Docker在linux安装
# 查看内核是否满足要求 >3.10
uname -r
# 卸载旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
# 安装依赖包
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
# 添加yum软件源
sudo yum-config-manager \
--add-repo \
https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
# 新版本的 Docker CE
sudo yum-config-manager --enable docker-ce-edge
# https://blog.csdn.net/qq_36643282/article/details/105190759
# 如果虚拟机是centos8.0 应该会报错 缺少containerd.io 执行下面命令单独处理
yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpm
# 查看是否安装 Podman
rpm -q podman
# 删除Podman 报错信息 :
#file /usr/share/man/man1/docker-attach.1.gz from install of docker-ce-cli-1:19.03.6-3.el7.x86_64 conflicts with file from package podman-manpages-1.4.2-5.module_el8.1.0+237+63e26edc.noarch
dnf remove podman
# 安装
sudo yum install docker-ce
# 启动
sudo systemctl enable docker
sudo systemctl start docker
# 测试是否安装成功
docker run hello-world
# 删除安装包
sudo yum remove docker-ce
# 删除镜像
sudo rm-rf /var/lib/docker
# 由于官方镜像速度慢,现在改为163服务器或者阿里云都可以
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://hub-mirror.c.163.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
# 查看docker镜像
docker images
# 删除镜像
docker rmi hello-world
# 列出所有的容器
docker ps -a
# 删除特定的容器(hello-world)
docker rm -f 7278d4e47dd3
Docker 常用命令
Docker 镜像操作
Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker会从镜像仓库下载该镜像。
Docker获取镜像
从仓库获取镜像的命令是 docker pull.
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
docker pull ubuntu:16.04
Docker运行
有了镜像后,我们就能够以这个镜像为基础启动并运行一个容器。
docker run -it --rm \ubuntu:16.04 \bash
- -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
- –rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
- ubuntu:16.04:这是指用 ubuntu:16.04 镜像为基础来启动容器。
- bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash。
Docker列出镜像
列表会包含 仓库名、标签、镜像 ID、创建时间 以及 所占用的空间。
docker image ls
docker images
**REPOSITORY:**表示镜像的仓库源
**TAG:**镜像的标签
**IMAGE ID:**镜像ID
**CREATED:**镜像创建时间
**SIZE:**镜像大小
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如 ubuntu 仓库源里,有 16.04、14.04 等多个不同的版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
虚悬镜像
由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 的镜像。这类无标签镜像也被称为 虚悬镜像(dangling image)
docker image ls -f dangling=true
一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,可以用下面的命令删除。
docker image prune
中间层镜像
docker image ls -a
这个命令会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错。实际上,这些镜像也没必要删除,因为之前说过,相同的层只会存一遍,而这些镜像是别的镜像的依赖,因此并不会因为它们被列出来而多存了一份,无论如何你也会需要它们。只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删除。
列出部分镜像
docker image ls 镜像名称
成批删除镜像
像其它可以承接多个实体的命令一样,可以使用 docker image ls -q 来配合使用 docker image rm,这样可以成批的删除希望删除的镜像。我们在“镜像列表”章节介绍过很多过滤镜像列表的方式都可以拿过来使用。
# 删除所有仓库名为 redis 的镜像
docker image rm $(docker image ls -q redis)
# 删除所有在 mongo:3.2 之前的镜像
docker image rm $(docker image ls -q -f before=mongo:3.2)
Docker容器操作
启动容器
启动容器有俩种方式,一种是基于镜像新建一个容器并启动,另外一种是将在终止状态(stopped)的容器重新启动.
新建启动
docker run
# 输出一个hello World之后,终止容器
docker run ubuntu:16.04 /bin/echo 'Hello World'
启动已终止的容器
# 启动命令
docker container start / docker start
# 启动一个bash终端,允许用户进行交互
docker run -t -i ubuntu:16.04 /bin/bash
-t 让Docker分配一个伪终端并绑定到容器的标准输入上, -i 让容器的标准输入保持打开。
当使用docker run 来创建容器时,docker在后台的操作。
- 检测本地是否存在指定的镜像,不存在就会从公有仓库下载。
- 利用镜像创建并启动一个容器。
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层。
- 从宿主主机配置的网络桥接口中桥接一个虚拟接口到容器中去。
- 从地址池配置一个ip地址给容器。
- 执行用户指定的应用程序。
- 执行完毕后容器被终止。
后台运行
# 会把日志打印在控制台
docker run hello-world
# 加 -d 不会把日志打印在控制台,只会打印id
docker run -d hello-world
# 查看输出结果信息
docker logs
停止运行的容器
# 查看容器
docker ps -a
# 停止运行的容器
docker container stop CONTAINER ID
# 终止状态的容器可以使用docker container ls -a 看到。
docker container ls -a
# 处于终止状态的容器,通过docker container start 来重新启动。
docker container start
# 会将一个正在运行的容器停止掉,再重新启动
docker container restart
进入容器
# 查看容器
docker ps -a
# 进入容器
docker exec -i -t CONTAINER ID /bin/bash
导出容器
# 查看容器
docker ps -a
# 导出容器
docker export CONTAINER ID > FileName.zip
导入容器
cat FileName.zip | docker import - 镜像用户/镜像名:镜像版本
删除容器
# 删除一个处于终止状态的容器
docker container rm ubuntu:16.04
# 删除运行时的容器
docker container rm -f ubuntu:16.04
# 清理所有处于终止状态的容器
docker container prune
构建私有镜像
使用Dockerfile定制镜像
镜像的定制就是定制每一层所添加的配置文件,我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本中,这个脚本就是Dockefile.
Dockerfile是一个文本文件,文件内包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述当层应该如何构建。
官方nginx为例,使用Dockerfile 进行定制。
# 创建文件夹、文件
mkdir mynginx
cd mynginx
touch Dockerfile
# Dockerfile内容
FROM nginx # 指定基础镜像
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
# Dockerfile 文件所在目录执行,构建镜像 最后有个点 代表使用当前路径的 Dockerfile 进行构建
docker build -t nginx:1.0 .
# 建立一个容器运行起来 nginx:1.0这个镜像
docker run --name webserver -d -p 80:80 nginx:1.0
从命令的输出结果中,我们可以清晰的看到镜像的构建过程。在 Step 2 中,如同我们之前所说的那样,RUN 指令启动了一个容器 2822ae1e0112,执行了所要求的命令,并最后提交了这一层 2ed331df1c3e,随后删除了所用到的这个容器 2822ae1e0112。
FROM 指定基础镜像
所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。就像我们之前运行了一个 nginx 镜像的容器,再进行修改一样,基础镜像是必须指定的。而 FROM 就是指定基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。
在 Docker Store 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如 nginx、redis、mongo、mysql、httpd、php、tomcat 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 node、openjdk、python、ruby、golang 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。
除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
FROM scratch
...
以 scratch 为基础镜像的话,意味着不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。
RUN 执行命令
有俩种格式
shell 格式:
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。
exec 格式:
RUN ["可执行文件", "参数1", "参数2"]
RUN make -C /usr/src/redis install
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。
以 && 符号连接命令,这样执行后,只会创建 1 层镜像。
FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz
构建镜像
# Dockerfile 文件所在目录执行,构建镜像 最后有个点 代表使用当前路径的 Dockerfile 进行构建
docker build -t mynginx:1.0 .
Dockerfile指令详解
COPY 复制文件
- COPY <源路径>… <目标路径>
- COPY ["<源路径1>",… “<目标路径>”]
COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
COPY package.json /usr/src/app/
需要注意一点,使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候。
ADD 更高级的复制文件
ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。
比如 <源路径> 可以是一个 URL,这种情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去。下载后的文件权限自动设置为 600,如果这并不是想要的权限,那么还需要增加额外的一层 RUN 进行权限调整,另外,如果下载的是个压缩包,需要解压缩,也一样还需要额外的一层 RUN 指令进行解压缩。所以不如直接使用 RUN 指令,然后使用 wget 或者 curl 工具下载,处理权限、解压缩、然后清理无用文件更合理。因此,这个功能其实并不实用,而且不推荐使用。
CMD 容器启动命令
CMD 指令的格式和 RUN 相似,也是两种格式:
shell 格式:CMD <命令>
exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
参数列表格式:CMD [“参数1”, “参数2”…]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
容器就是进程,既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。
在运行时可以指定新的命令来替代镜像设置中的这个默认命令,比如,ubuntu 镜像默认的 CMD 是 /bin/bash,如果我们直接 docker run -it ubuntu 的话,会直接进入 bash。我们也可以在运行时指定运行别的命令,如 docker run -it ubuntu cat /etc/os-release。这就是用 cat /etc/os-release 命令替换了默认的 /bin/bash 命令了,输出了系统版本信息。
在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 ",而不要使用单引号。
ENTRYPOINT 入口点
ENTRYPOINT 的格式和 RUN 指令格式一样,分为 exec 格式和 shell 格式。
ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:
<ENTRYPOINT> "<CMD>"
ENV 设置环境变量
格式有两种:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
这个指令很简单,就是设置环境变量而已,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。
ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"
ARG 构建参数
格式:ARG <参数名>[=<默认值>]
构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的。
Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。
VOLUME 定义匿名卷
格式为:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
之前我们说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中,后面会进一步介绍 Docker 卷的概念。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
VOLUME /data
这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行时可以覆盖这个挂载设置.
docker run -d -v mydata:/data xxxx
在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。
EXPOSE 暴露端口
格式为 EXPOSE <端口1> [<端口2>...]
EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
WORKDIR 指定工作目录
格式为 WORKDIR <工作目录路径>。
使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。
USER 指定当前用户
格式:USER <用户名>
USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。WORKDIR 是改变工作目录,USER 则是改变之后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。
当然,和 WORKDIR 一样,USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。
RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]
HEALTHCHECK 健康检查
格式:
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常,这是 Docker 1.12 引入的新指令。
通过该指令指定一行命令,用这行命令来判断容器主进程的服务状态是否还正常,从而比较真实的反应容器实际状态。
ONBUILD 为他人作嫁衣
格式:ONBUILD <其它指令>
ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
Dockerfile 中的其它指令都是为了定制当前镜像而准备的,唯有 ONBUILD 是为了帮助别人定制自己而准备的。
Docker运行java程序
定制镜像
# 基础镜像使用tomcat:7.0.88-jre8
FROM tomcat:7.0.88-jre8
# 作者
MAINTAINER weizhengyu<weizhengyu@163.com>
# 定义环境变量
ENV TOMCAT_BASE/usr/local/tomcat
# 复制war包
COPY ./session-web-0.0.1-SNAPSHOT.war $TOMCAT_BASE/webapps/
执行构建
docker build -t session-web:1.0 .
运行
# 第一个port 代表虚拟机地址只是一个映射 第二个port代表容器中的真实端口
docker run --name session-web -d -p 8080:8080 session-web:1.0
使用docker搭建weblogic环境
# 搜索镜像
docker search weblogic
# 拉取镜像
docker pull ismaleiva90/weblogic12
# 启动
docker run -d -p 7001:7001 -p 7002:7002 ismaleiva90/weblogic12:latest
构建docker私有仓库
https://hub.docker.com/ 免费注册一个 Docker 账号
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4j8uGPGE-1594013534862)(docker.assets/image-20200628231013794.png)](https://img-blog.csdnimg.cn/20200706133632920.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzcwNTMxMw==,size_16,color_FFFFFF,t_70)
# 登录
docker login
# 退出
docker logout
# 拉取镜像
docker search 镜像名称
docker pull 镜像名称
# 修改镜像名称
#docker tag 镜像ID 17634991926/hello-word:latest
docker tag bf756fb1ae65 17634991926/hello-word:latest
#推送镜像
docker push 17634991926/hello-word:latest
私有仓库
docker-registry 是官方提供的工具,可以用于构建私有的镜像仓库。
安装运行 docker-registry
docker run -d -p 5000:5000 --restart=always --name registry registry
docker run -d \
-p 5000:5000 \
-v /usr/local/Docker/registry:/var/lib/registry \
registry
# 改名称
docker tag session-web:1.0 127.0.0.1:5000/session-web:1.0
# 推送到私有仓库
docker push 127.0.0.1:5000/session-web:1.0
# 查看私有仓库镜像
curl 127.0.0.1:5000/v2/_catalog
# 删除本地镜像
docker image rm 127.0.0.1:5000/session-web:1.0
# 从私有仓库拉取
docker pull 127.0.0.1:5000/session-web:1.0
# 查看所有镜像
docker image ls
如果你不想使用 127.0.0.1:5000 作为仓库地址,比如想让本网段的其他主机也能把镜像推送到私有仓库。你就得把例如 192.168.125.130:5000 这样的内网地址作为私有仓库地址,这时你会发现无法成功推送镜像。
这是因为 Docker 默认不允许非 HTTPS 方式推送镜像。我们可以通过 Docker 的配置选项来取消这个限制,或者查看下一节配置能够通过 HTTPS 访问的私有仓库。
vim /etc/docker/daemon.json
{
"registry-mirrors": [
"https://registry.docker-cn.com"
],
"insecure-registries": [
"192.168.125.130:5000"
]
}
125网段都可以。
数据挂载
主要目标是学习如何在容器内部管理数据或者多个容器之间管理数据。
Docker容器内部管理数据
在容器中管理数据的方式主要有两种:
数据卷(Volumes)
挂载主机目录(Bind mounts)
数据卷:是一个可以提供一个或者多个容器使用的特殊目录,它绕过UFS,可以提供很多有用的特性;
- 数据卷可以在容器之间共享和重用
- 对数据卷的修改会立马生效
- 对于数据卷的更新不会影响镜像
- 数据卷会默认会一直存在,即使容器被删除
数据卷的使用,类似于Linux下对目录或者文件进行mount,镜像中的被指定为挂载点的目录中的文件会被隐藏掉,能显示看到的是挂载的数据卷。
docker中提供了两种挂载方式
-v
-mount
推荐使用 --mount 参数
创建一个数据卷
docker volume create test
查看所有的数据卷
docker volume ls
查看指定 数据卷
docker volume inspect my-vol
删除数据卷
docker volume rm test
清理无主的数据卷
docker volume prune
数据卷是被设计用来持久化数据的,它的生命周期独立于容器。Docker不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷。
启动一个挂载数据卷的容器
在用 docker run 命令的时候,使用 --mount 标记来将 数据卷 挂载到容器里。在一次 docker run 中可以挂载多个 数据卷。
创建一个名为session-web的容器,并加载一个数据卷到容器的/webapp目录
docker run --name web \
-d -P 8080:8080 \
# -v my-vol:/wepapp \
--mount source=test,target=/webapp \
session-web:1.0
挂载一个主机目录作为数据卷
使用 --mount 标记可以指定挂载一个本地主机的目录到容器中去。
docker run --name web \
-d -P 8080:8080 \
# -v test:/wepapp \
--mount type=bind,source=/src/webapp,target=/opt/webapp \
session-web:1.0
说明:命令是加载主机的/src/webapp 目录到容器的/opt/webapp目录,这个功能在测试时候很方便,用户可以放一些程序到本地目录(绝对路径),来查看容器是否正常工作。
挂载一个本地主机文件作为数据卷
–mount 标记也可以从主机挂载单个文件到容器中
docker run --rm -it \
# -v $HOME/.bash_history:/root/.bash_history \
# 把容器中的历史命令挂载到主机上的历史命令 文件,记录在容器输入过的命令。
--mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history \
ubuntu:17.10 \
bash
Compose集成式应用组合
简介
Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。自身定位:定义和运行多个Docker容器的应用。
允许用户通过一个单独的docker-compose.yml模板文件来定义一组相关联的应用容器为一个项目。
Compose中有俩个概念:
服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
项目 (project) :由一组关联的应用容器组成的一个完整业务单元。
Compose默认管理对象是项目,通过子命令对项目的一组容器进行便捷的生命周期管理。
Compose项目有python编写,实现上调用了Docker服务提供的API来对容器进行管理。
安装和卸载
在 Linux 64 位系统上直接下载对应的二进制包 安装。
sudo curl -L https://github.com/docker/compose/releases/download/1.17.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
pip方式安装
sudo pip3 install -U docker-compose
一个项目是由多个应用容器(服务)关联而成的,Compose面向项目管理。
案列 Compose构建dubbo-admin服务
准备工作(建立一个文件夹)
/usr/local/Docker/dubbo-admin
获取源码
git clone -b master https://github.com/apache/incubator-dubbo-ops.git
修改/incubator-dubbo-ops/dubbo-admin/src/main/resources中的application.properties配置,修改zookeeper地址为 zookeeper://zookeeper:2181
在/incubator-dubbo-ops 目录下使用 maven编译打包
mvn clean package -Dmaven.test.skip=true
Dockerfile文件
在/incubator-dubbo-ops/dubbo-admin目录下编写Dockerfile文件
# FROM 表示使用JDK8环境为基础镜像,如果镜像不是本地的会从DockerHub下载
FROM openjdk:8-jdk-alpine
# 作者
MAINTAINER weizhengyu<weizhengyu>
VOLUME /tmp
# ADD拷贝文件并且重命名
ADD ./target/dubbo-admin-0.0.1-SNAPSHOT.jar app.jar
# ENTRYPOINT 为了缩短Tomcat启动时间
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
构建
docker build -t dubbo-admin:1.0 .
在 /incubator-dubbo-ops/ 编写 docker-compose.yml 文件,这个是 Compose 使用的主模板文件。
冒号前端口是本地虚拟机的实际端口,冒号后边的是容器内的端口。
version: '3.4'
services:
zk_server:
image: zookeeper:3.4
ports:
- 2181:2181
dubbo-admin:
image: dubbo-admin:1.0
links:
- zk_server:zookee per
ports:
- 7001:7001
运行 compose 项目
docker-compose up
compose命令说明
docker-compose
命令选项:
-f 指定模板文件 默认为 docker-compose.yml 可以多次指定。
-p 指定项目名称 默认文件目录名作为项目名
-v 打印版本
docker-compose build
构建(重新构建)项目中的服务容器。
- –force-rm 删除构建过程中的临时容器。
- –no-cache 构建镜像过程中不使用 cache(这将加长构建过程)。
- –pull 始终尝试通过 pull 来获取更新版本的镜像。
docker-compose config
验证 Compose 文件格式是否正确,若正确则显示配置,若格式错误显示错误原因。
docker-compose down
停止 up 命令所启动的容器,并移除网络
docker-compose exec
进入指定的容器。
docker-compose images
列出 Compose 文件中包含的镜像。
docker-compose kill
通过发送 SIGKILL 信号来强制停止服务容器。
docker-compose logs
查看服务容器的输出。
docker-compose pause
暂停一个服务容器。
docker-compose port
打印某个容器端口所映射的公共端口。
- –protocol=proto 指定端口协议,tcp(默认值)或者 udp。
- –index=index 如果同一服务存在多个容器,指定命令对象容器的序号(默认为 1)。
docker-compose ps
列出项目中目前的所有容器。
docker-compose pull
拉取服务依赖的镜像。
- –ignore-pull-failures 忽略拉取镜像过程中的错误。
docker-compose push
推送服务依赖的镜像到 Docker 镜像仓库。
docker-compose restart
重启项目中的服务。
docker-compose rm
删除所有(停止状态的)服务容器。推荐先执行 docker-compose stop 命令来停止容器。
- -f, --force 强制直接删除,包括非停止状态的容器。一般尽量不要使用该选项。
- -v 删除容器所挂载的数据卷。
docker-compose run
在指定服务上执行一个命令。
docker-compose scale
设置指定服务运行的容器个数。(扩容)
eg:docker-compose scale web=3 db=2 —> 将启动 3 个容器运行 web 服务,2 个容器运行 db 服务。
docker-compose start
启动已经存在的服务容器。
docker-compose stop
停止已经处于运行状态的容器,但不删除它。通过 docker-compose start 可以再次启动这些容器。
docker-compose top
查看各个服务容器内运行的进程。
docker-compose unpause
恢复处于暂停状态中的服务
docker-compose up
该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。如果使用 docker-compose up -d,将会在后台启动并运行所有的容器。一般推荐生产环境下使用该选项。默认情况,如果服务容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml 文件的最新内容。如果用户不希望容器被停止并重新创建,可以使用 docker-compose up --no-recreate。这样将只会启动处于停止状态的容器,而忽略已经运行的服务。如果用户只想重新部署某个服务,可以使用 docker-compose up --no-deps -d <SERVICE_NAME> 来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。
- -d 在后台运行服务容器。
- –no-color 不使用颜色来区分不同的服务的控制台输出。
- –no-deps 不启动服务所链接的容器。
- –force-recreate 强制重新创建容器,不能与 --no-recreate 同时使用。
- –no-recreate 如果容器已经存在了,则不重新创建,不能与 --force-recreate 同时使用。
- –no-build 不自动构建缺失的服务镜像。
- -t, --timeout TIMEOUT 停止容器时候的超时(默认为 10 秒)。
docker-compose version
打印版本信息
Docker监控
容器监控
docker-compose 启动服务都在一台宿主机上,对于一个宿主机上运行多个容器,容器的运行情况比如CPU ,内存,网络状态 等一系列随时间变化的时序数据信息,都是需要监控的。
监控方案
docker stats 可以很方便的看到当前宿主机所有容器的详细信息。但是docker stats 有很大的缺点,统计的只可以是当前宿主机的所有的容器,并且获取的监控数据都是实时的,没有地方存储,也没有报警功能。
docke stats
CAdvisor 谷歌出品,是一个容器资源监控工具,包括容器的内存 cpu 等监控,同时提供了一个web页面用来查询容器的实时运行状态,有官方的docker镜像。但是集成度不高,默认在本地保存2分钟的数据。不过可以加influxDB存储数据,再对接Grafana 展示图表。
案列:
cAdvisor+InfluxDB+Grafana
创建一个docker-compose.yml文件 (touch docker-compose.yml )
version: '3.1'
volumes:
grafana_data: {}
services:
influxdb:
image: tutum/influxdb:0.9
#image: tutum/influxdb
#image: influxdb
restart: always
#user:
environment:
- PRE_CREATE_DB=cadvisor
ports:
- "8083:8083"
- "8086:8086"
expose:
- "8090"
- "8099"
volumes:
- ./data/influxdb:/data
cadvisor:
#image: google/cadvisor:v0.29.0
image: google/cadvisor
links:
- influxdb:influxsrv
command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
restart: always
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
grafana:
#image: grafana/grafana:2.6.0
user: "104"
image: grafana/grafana
user: "104"
#user: "472"
restart: always
links:
- influxdb:influxsrv
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- HTTP_USER=admin
- HTTP_PASS=admin
- INFLUXDB_HOST=influxsrv
- INFLUXDB_PORT=8086
- INFLUXDB_NAME=cadvisor
- INFLUXDB_USER=root
- INFLUXDB_PASS=root
执行命令
docker-compose up
会下载需要的镜像,几分钟可以完成。
influxDB 访问地址:IP+8083
cAdvisor 访问地址:IP+8080
Grafana 访问地址:IP+3000
注意事项:
yml 中建立服务cadvisor ,–link后跟要连接的influx容器名,-storage_driver_db后跟influxdb数据库名,-storage_driver_host后跟influx容器名:8086
influxdb 中必须创建一个数据库,cadvisor ,然后进行配置。
在Grafana 进行配置 datasource .
查询编辑器的配置。
总结:使用CAdvisor+influxDB+Grafana 构建容器资源监控系统,是可行的而且是较为简便的,三个组件完全以容器的方式运行,符合线上服务结尾容器的理念。
日志监控
Doxker日志处理机制,当启动一个容器时,其实是docker daemon 的一个子进程,docker daemon 可以拿到内容器里面进程的标准输出,然后通过自身的一个logDriver模块来处理。logDriver支持的方式很多,默认方式写到本地的文件(json.log),也可以发送到syslog等。
Docker默认会收集应用程序的标准输出存储到一个json.log文件中。
Graylog
我们使用gelf ,将日志写到Graylog,俩个原因:
1、Docker原生支持graylog协议,直接将日志发送到graylog(通过gelf协议)。
2、graylog 官方提供了 将本身部署在Docker的支持。
搭建graylog,日志监控。准备工作
# 分别安装 mongo elasticsearch graylog
# 根据自己的IP进行修改即可
docker run \
--name mongo \
-p 27017:27017 \
-v /etc/localtime:/etc/localtime:ro \
-v mongo_data:/data/db \
-d mongo:latest
docker run \
--name elasticsearch \
-p 9200:9200 -p 9300:9300 \
-e "http.host=0.0.0.0" \
-e "ES_JAVA_OPTS=-Xms256m -Xmx256m" \
-e "discovery.type=single-node" \
-e http.cors.allow-origin="*" \
-e http.cors.enabled=true \
-v /etc/localtime:/etc/localtime:ro \
-v es_data:/usr/share/elasticsearch/data \
-d docker.elastic.co/elasticsearch/elasticsearch-oss:6.8.5
docker run \
--link mongo \
--link elasticsearch \
--name graylog \
-p 9000:9000 \
-p 12201:12201 -p 12201:12201/udp \
-p 1514:1514 -p 1514:1514/udp -p 5044:5044 \
-e GRAYLOG_HTTP_EXTERNAL_URI=http://192.168.125.131:9000/ \
-e GRAYLOG_ROOT_TIMEZONE=Asia/Shanghai \
-e GRAYLOG_WEB_ENDPOINT_URI="http://192.168.125.131:9000/:9000/api" \
-e GRAYLOG_PASSWORD_SECRET=somepasswordpepper \
-e GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 \
-v /etc/localtime:/etc/localtime:ro \
-v graylog_journal:/usr/share/graylog/data/journal \
-d graylog/graylog:3.1
下来启动一个nginx来 监控日志。
version: '2'
services:
nginx:
image: nginx:latest
ports:
- "80:80"
logging:
driver: "gelf"
options:
gelf-address: "udp://192.168.125.131:12201"
tag: front-nginx
接着访问nginx,然后在graylog刷新即可看到日志。
Docker Swarm 资源管理
简介
docker swarm 提供了Docker 容器集群服务,是Docker官方对容器云生态进行支持的核心方案。
使用它可以将多个Docker主机封装成单个大型的虚拟Docker主机,快速打造一套容器云平台。
Swarm是使用SwarmKit构建的Docker引擎内置的集群管理和编排工具。
节点:
运行Docker的主机可以主动初始化一个Swarm集群或者加入一个已存在的Swarm集群,这样这个运行的Docker的主机就成为了swarm集群的一个节点。
节点分为管理节点和工作节点
管理节点:用于swarm集群的管理,docker swarm 命令基本只能在管理节点执行。
工作节点:是任务执行节点,管理节点将服务下发至工作节点。
服务和任务
任务(Task):是swarm中最小的调度单位,目前来说就是一个单一的容器。
服务(services):指一组任务的集合,服务定义了任务的属性。
搭建swarm集群
准备三台虚拟机
192.168.125.130(工作节点)
192.168.125.131(管理节点)
192.168.125.132(工作节点)
在管理节点执行:
docker swarm init
会打印出一段话,直接粘贴到另外两台工作节点执行即可。
docker swarm join --token SWMTKN-1-2anqlt4m1s25psxsg20nbaey2y0mactza2jwj34c8cuc2r2yg4-07cj9mmupgbsp8mhonlsf4w89 192.168.125.131:2377
如果忘记了这个命令:可以再次输入查看 :
docker swarm join-token manager
将工作节点升级为管理节点:
docker node promote HOSTNAME(节点的主机名,在下边截图中看)
在管理节点查看集群:
docker node ls
集群搭建完毕。
部署集群服务
使用docker service 来管理Swarm集群中的服务,该命令只能在管理节点使用。
新建服务
# 启动三个副本 指定端口 镜像是nginx最新版 ,安装完成后,三个节点都可以访问。
docker service create --replicas 3 -p 80:80 --name nginx nginx:latest
查看服务
# 查看集群中运行的服务
docker service ls
# 查看某个服务的详情
docker service ps nginx
# 查看某个服务的日志
docker service logs nginx
删除服务
# 移除某个服务
docker service rm nginx
swarm中没有提供统一入口查看节点的资源使用情况。图形化管理工具,portainer出现了。
安装portainer
docker search portainer
docker pull portainer/portainer
docker run -d -p 9000:9000 \
--name portainer --restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
portainer/portainer
快速扩容
有俩种方式:
1)命令方式、
# 在swarm集群中运行一个nginx服务,使用replicas指定启动的副本数
docker service create --replicas 3 -p 80:80 --name nginx nginx:latest
# 使用 scale
docker service create -p 80:80 --name nginx nginx:latest
docker service scale nginx=3
#查看副本情况
docker service ls
2)portainer方式
使用portainer在web页面创建服务并指定副本数,同时可以动态的增减副本数。