ᕕ( ᐛ )ᕗ xiaoli's blog

云原生之docker入门

; 3396 words  

目录

是什么

通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的应用程序及其运行环境能做到一次镜像,处处运行

为什么

传统虚拟机技术基于安装在主操作系统上的虚拟机管理系统(如VirtualBox、VMware等),创建虚拟机(虚拟出各种硬件),在虚拟机上安装从操作系统,在从操作系统中安装部署各种应用。

缺点:资源占用多、冗余步骤多、启动慢

Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一的运行。

主要概念

容器:容器可以独立运行应用,应用程序或服务运行在容器里面,容器就类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。每个容器相互隔离。

镜像:一个只读的模板。镜像可以用来创建Docker容器,一个镜像可以创建多个容器。一般会把可运行系统打包成一个镜像。

仓库:集中存放镜像文件的场所。https://hub.docker.com/

docker_host:安装docker的主机

docker deamon: 守护进程,运行在docker主机上的docker后台进程。

​ 守护进程:在后台运行并提供某种服务的进程,它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。

docker本质上是一个容器运行载体,我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个运行环境就是image镜像文件,通过该镜像文件生成docker容器实例。

  1. 从 Docker Registry 中下载镜像,并通过镜像管理驱动 Graph Driver 将下载镜像以 Graph 的形式存储
  2. 通过网络管理驱动 Network driver 创建并配置 Docker 容器网络环境
  3. 通过 Exec driver 来完成限制 Docker 容器运行资源或执行用户指令等
  4. Libcontainer 是一项独立的容器管理包,Network driver 以及 Exec driver 都是通过Libcontainer 来实现具体对容器进行的操作

docker命令实战

安装docker

其他系统参照如下文档 https://docs.docker.com/engine/install/centos/

  1. 移除其他docker安装包
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 配置yum源
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 安装docker。docker-ce是社区版,docker-ce-cli是操作docker的命令行工具,containerd.io是docker的容器化工具。
sudo yum install -y docker-ce docker-ce-cli containerd.io
  1. 配置自启动
systemctl enable docker --now
  1. 配置镜像加速,参考https://cr.console.aliyun.com/cn-beijing/instances/mirrors
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://rvzmkti6.mirror.aliyuncs.com"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

常用命令

可以访问https://hub.docker.com/镜像仓库寻找镜像。

拉取镜像

docker pull nginx   # 最新版本

docker pull nginx:1.20.1 # 指定版本

 # 列出本地所有镜像。
 # 可以查询到镜像的tag、image id、size等信息
docker images

docker rmi nginx # 删除镜像,参数需要是镜像名:镜像版本号/镜像id

启动容器

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 当前正在运行的应用容器信息
docker ps

# 显示所有的容器
docker ps -a

# -d:后台运行
# --name=xx 自定义名称
# --restart=always 开机自启动
# 返回的序列号其实就是containerID
docker run --name=mynginx -d --restart=always nginx

# 镜像name不能重复

docker rm containerID/name # 删除应用容器,可以使用-f强制删除

docker stop containerID/name # 停止应用

docker start containerID/name # 启动应用

docker update containerID/name --restart=always # 使用update更新配置项,但是无法修改端口配置

目前nginx在云容器的80端口工作,无法通过公网ip访问,但是可以使用docker进行端口映射。docker run --name=mynginx -p 88:80 nginx
docker从镜像仓库拉取nginx镜像,使用docker run可以运行nginx应用,也可以使用exec进入应用配置。

docker run

修改容器应用

# 进入容器应用的/bin/bash目录
docker exec -it [containerID/name] /bin/bash 

exit # 离开应用

# 挂载数据
docker run --name=mynginx -d -p 88:80 \
-v /data/html:/usr/share/nginx/html:ro \  
nginx
# 把nginx应用的/usr/share/nginx/html文件挂载到云容器的/data/html文件,权限设置为只读模式,表示容器内部不能修改。此时修改外部文件其实就是修改内部文件
需要注意:挂载中设置的参数文件需要已存在

# 复制应用中指定位置的文件到容器文件中,容器文件和镜像文件可以互相复制
docker cp [containerID/name]:/etc/nginx/nginx.conf /data/conf/nginx.conf 

提交镜像

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] #提交到本地仓库,提交后本地仓库命名repository:tag(类似git)
[OPTIONS]
-a author
-m commit message

docker save [OPTIONS] IMAGE [IMAGE...]
[OPTIONS]
-o 后接文件名,如abc.tar,把镜像保存成压缩实体文件,方便传输

docker load -i abc.tar 加载接收的镜像文件

将镜像推送到远程仓库需要先在docker hub创建对应的repository
docker tag local-image:tagname new-repo:tagname #将本地镜像名称改成远程镜像名称

docker login # 登陆docker hub

docker push new-repo:tagname # 将镜像推送到远程仓库

docker logout

常用命令

docker logs containerID/name # 查看镜像日志

应用的打包和发布

程序被打成可执行的jar包,终端输入java -jar xx.jar即可运行应用。但是这种运行的前提是需要拥有java运行环境。
此时使用docker,任何应用都是镜像,解决跨语言下的程序运行问题。

  1. 编写Dockerfile。
FROM unitfinance/jdk17-sbt-scala:latest  # 程序的运行环境
LABEL maintainer=xiaoli  # 作者
  
COPY target/*.jar /app.jar  # 将程序复制到容器
  
ENTRYPOINT ["java","-jar","demo-0.0.1-SNAPSHOT.jar"] # 运行命令
  1. 将jar包上传到docker容器。注意-r是递归复制目录
  2. 在docker容器中构建镜像docker build -t java-demo:v1.0 -f Dockerfile .。构建成功后可以使用docker images查看镜像。
    镜像有752mb,是因为携带了jdk17的基础环境。
  3. docker run -d -p 8080:8080 java-demo:v1.0。启动镜像。
  4. docker ps 查看容器是否启动成功。启动后就可以正常运行应用。
  5. docker logs`查看程序的运行日志。

在后续的流程中,可以将镜像上传到docker hub,只需要从dockerhub中拉取镜像,不同的服务器就可以实现镜像的共享,使用docker run,就可以跨语言的运行应用。
其实大多数人谈论 Docker 时说的是 Docker Engine,这只是一个构建和运行的容器。

在运行容器前需要编写Docker File,通过 dockerFile 生成镜像,然后才能运行 Docker 容器。

Docker File 定义了运行镜像(image)所需的所有内容,包括操作系统和软件安装位置。一般情况下都不需要从头开始编写 Docker File,在 Docker Hub 中有来自世界各地的工程师编写好的镜像,可以基于此修改。

Docker File

docker file是用来构造docker镜像的文本文件,由多条构建镜像所需的指令和参数构成的脚本。 保留字指令大写字母,后面要至少跟随一个参数,每条指令会创建一个新的镜像层并对镜像进行提交。

FROM 指定基础镜像,当前镜像基于该镜像构建

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

RUN 容器构建(docker build)时需要运行的命令

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

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

USER 镜像执行用户,默认root

ENV 镜像运行时环境配置

VOLUMN 容器卷,用于数据持久化

ADD 将宿主机目录下的文件拷贝到镜像并自动处理URL、解压tar压缩包。

COPY 类似于ADD,拷贝文件和目录到镜像。COPY src dst

CMD 容器启动后会执行的命令,多个CMD指令只有最后一个会生效。会被docker run后的参数取代。

EMTRYPOINT 指定容器启动要执行的指令。但不会被docker run后的参数取代,可以和CMD一起使用,此时CMD起到传递参数的作用。

docker-compose 容器编排

docker-compose负责对docker容器集群的快速编排,需要定义一个docker-compose.yml,定义多个关联容器之间的依赖关系,作为一组应用。
服务:应用容器实例。
工程:一组关联的应用容器组成完整项目单元。
配置docker-compose.yml后,使用docker-compose up启动运行整个应用程序。

#docker