前提
本文对 Docker 进行全面阐述,详细介绍 Docker 的作用、其基本使用,如常用命令、Dockerfile 的作用及使用、Docker Compose 的作用及使用。常用的基本上都会涉及,其他可以在 Docker 官网进行查漏补缺。
下面还有投票,一起参与进来吧👍
Docker 的作用
这里以容器化发展历程加上应用部署为例子,对 Docker 的作用进行说明。
在只有物理机的时候,大多数开发者或运维人员在部署一个应用时要做以下操作(以 java 应用为例):搭建 java 环境、maven 环境、配置环境变量、打包、运行。这样有几个问题:
- 部署慢:以上的过程都是需要手动操作,中间但凡那个环节出问题都需要花费时间排查,而且每次部署都需要重复做同样的操作。
- 成本高:一个外网的服务器费用最起码以万为单位进行采购,成本相对高。
- 资源浪费:如果应用是计算密集型,那么对 cpu 要求会很高,对内存、磁盘要求就不高,这样一来,闲置的资源就会浪费掉。
- 难于扩展迁移:如果要将 windows 服务器的应用迁移到 linux 服务器,一定会出现各种问题。
在虚拟化技术出现后,可以在物理机上开辟多个虚拟机,对物理机的资源进行了充分的使用,且虚拟机之间的资源是隔离的,可以部署多个应用,也降低了成本。 但是虚拟机需要安装操作系统,同样会造成资源浪费。
为了解决虚拟机安装操作系统带来的资源浪费,容器化技术就诞生了,容器化可以理解成不用安装操作系统的虚拟机,如下图,
这里的 Docker 就是容器化技术最典型的代表,其通过沙箱机制依赖主操作系统,大大的节省了资源、降低成本。除此之外,在应用部署上,Docker 容器本质是包含了部署应用所需的一切资源,包括操作系统依赖的其他组件或应用、数据库、配置等,这样在任何的环境下进行部署时将容器里的资源展开即可部署成功。
比如:我们现在使用 redis 服务,我们不需要去下载redis安装包、gcc等依赖组件等操作,只需要拉取 redis 镜像运行即可。
所以 Docker 的作用不仅仅是节省资源、降低成本,在应用方面也做到了自动部署、应用监控的作用,更简化了开发与运维的沟通,让软件协作方式发生巨大变化。
Docker 安装
这里基于 CentOS 7 进行 Docker 安装,Windows 和 MAC 安装参考 Docker 官网。
执行以下命令进行安装
yum install -y yum-utils
#设置仓库地址
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl start docker
Docker 常用命令
拉取镜像:docker pull 镜像名:<tag>
。 可以通过配置镜像加速器加快拉取镜像的速度,可以参考阿里云 容器镜像服务中的镜像加速器 。
查看镜像:docker images
启动容器:docker run 镜像名:<tag>
查看容器:docker ps
删除容器:docker rm <-f> 容器id
删除镜像:docker rmi 镜像名:<tag>
与容器交互:docker exec <-it> 容器id /bin/bash
容期间通信
一个宿主机上的容器默认是可以互相通信的,但是每次启动容器后ip会修改,避免因ip变动而修改配置,启动容器时可以给容器命名,通过容器名称通信。命令如下
docker run --name 容器名称 镜像名称 --link 要通信的容器名称 要通信的镜像名称
如果多个容器都需要互相通信,这种方式就会比较繁琐了,此时可以通过创建一个网桥,需要通信的容器都绑定这个网桥即可。命令如下:
#创建网桥
docker network create -d bridge 网桥名称
#绑定网桥
docker network connect 网桥名称 容器名称
Docker 数据卷
为避免容器中产生的数据丢失或者多个容器共享一份数据,Docker 提供了2种数据挂载的方式:
挂载到宿主机:宿主机开辟空间,容器内部文件存储在宿主机上,并访问同一份文件。命令如下:
docker run --name 容器名称 -v 宿主机目录:容器目录 镜像名称
挂载到共享容器:新建一个容器专门提供其他容器来存储或共享数据,命令如下:
#创建共享容器 docker create --name 容器名称 -v 宿主机目录:容器目录 镜像名称 /bin/true #挂载到共享容器 docker run --name 容器名称 --volumes-from 共享容器名称 镜像名称
Dockerfile 构建镜像
当需要自己创建一个镜像时可以通过 Dockerfile 来构建镜像,然后上传到镜像仓库(可以自建 Harbor 或者使用公网的),需要使用的直接拉取下来即可。构建命令如下
docker build -t 机构/镜像名:<tag> dockerfile目录
docker 会基于 Dockerfile 文件中的指令来构建,具体指令如下:
FROM 镜像名 #基准镜像,基于该镜像构建
MAINTAINER xxxxx #用来描述的
WORKDIR 工作目录 #进入容后设置工作目录,相当于cd /xxx/
ADD ooo /xxx #复制本地文件ooo到容器中的工作目录 /xxx
ADD ooo.tar.gz /xxx # 复制并解压 ooo.tar.gz 到容器中的工作目录 /xxx
ENV XXX #设置环境常量,文件中可以以${XXX}方式进行使用
运行指令有 RUN、CMD、ENTRYPOINT,其区别为:
- RUN:Build 构建容器时执行
- CMD:容器启动时执行的默认命令和参数,如果容器启动时有其他命令,则CMD不生效
- ENTRYPOINT:容器启动时执行的命令,只有最后一个ENTRYPOINT执行
运行指令有两种声明方式:
- Shell脚本方式:
RUN yum install xxx
- Exec函数方式(推荐此方式):
["yum","install","xxx"]
两者的区别在于一个会创建子进程执行,一个会用新的进程替换主进程执行。
Docker Compose 容器编排
在多个容器存在依赖,比如运行应用的容器依赖数据库、Redis等多个容器都需要部署的情况下,为了减少部署时间,可以通过 Docker Compose 将这个应用及其依赖的容器统一定义,达到一键部署效果,这个我们叫做容器编排。
在进行容器编排时需要声明 docker-compose.yml
文件定义各个容器以及依赖关系,然后执行 docker-compose up -d
命令进行容器启动。下面提供一个 docker-compose.yml
示例:
version: '1.0'
services:
service1: # 容器名、可通过此进行通信
build: service1 dockerfile目录
restart: always # 容错机制,当容器宕机后自动重启
environment: # 启动容器时添加环境变量
环境变量: xxxx
service1:
build: service2 dockerfile目录
depends_on: # 依赖某个容器,并可进行通信
- service1
ports: # 端口映射
- '宿主机端口:容器端口'
restart: always # 容错机制,当容器宕机后自动重启
需要注意的是 Docker Compose只能单机,能力有限。集群或者其他复杂场景k8s可以更好的满足。