Docker基础使用
微服务与容器共同构成了云原生应用开发的基础。
微服务是一种用于构建应用的架构方案,是松散耦合的分布式架构框架。微服务可通过分布式部署,大幅提升您的团队和日常工作效率。
容器可为基于微服务的应用提供理想的应用部署单元和独立的执行环境。通过将微服务放入容器,就能更好地利用硬件,轻松地编排各种服务(包括存储、网络和安全防护)。
容器技术
why containers?
传统的应用部署方式是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。
新的方式是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。
容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚机轻量、更“透明”,这更便于监控和管理。
Container vs. VM
下列左图为os层的虚拟化架构(典型如docker容器),右图为全虚拟化架构(典型如虚拟机VM),区别在于:
- VM是在宿主机器操作系统的基础上创建虚拟化的操作系统,需要重新加载一个Guest OS。
- Docker是在宿主操作系统上运行Docker引擎,在引擎的基础上再安装应用。
- Docker是共享宿主机的内核,有着比VM更少的抽象层。
what is Kubernetes?
Kubernetes(也称 k8s 或 “kube”)是一 个开源的容器编排平台,可以自动完成在部署、管理和扩展容器化应用过程中涉及的许多手动操作。
可以在物理或虚拟机的Kubernetes集群上运行容器化应用,Kubernetes能提供一个以“容器为中心的基础架构”,满足在生产环境中运行应用的一些常见需求。
Docker 概念
docker 组成:
- Docker Client 客户端
- Docker Daemon 守护进程
- Docker Image 镜像
- Docker Container 容器
三个基本概念:
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。
- 容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
Docker 安装
- 使用 Homebrew 安装
- 手动下载安装
docker 版本
macOS 从 Applications 中点击启动运行 Docker.app,然后在终端控制台即可输入 docker
相关命令。
输入 docker --version
查看当前 docker 版本:
$ docker --version
Docker version 20.10.8, build 3967b7d
注意 Docker Desktop 进程不要退出,否则执行 docker 命令报错:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
docker 帮助
执行 docker --help
或 docker help
查看 docker 命令帮助:
- Management Commands: 管理命令。
- Commands: 普通命令。
- Run
docker COMMAND --help
ordocker help COMMAND
:查看具体命令的帮助。
docker 常用命令
login
docker login 命令登录远程镜像仓库。
用法:
Usage: docker login [OPTIONS] [SERVER]
- 执行
docker login hub.aliyun.com
,然后按照提示,依次输入 Username 和 Password。 - 在 OPTIONS 位置,通过
-u name
和-p pwd
选项指定用户名和密码参数。
pull
从服务器拉取指定镜像:
$ docker pull hub.aliyun.com/sdet_dev/app:d_nginx_d5343399
冒号前面为 REPOSITORY,冒号后面为镜像tag,如果不指定则 Using default tag: latest。
images
执行 docker images
或 docker image ls
命令,可以查看本地已经 pull 下来的镜像,包括 REPOSITORY、TAG、IMAGE ID等信息。
docker images
# or
docker image ls
run & ps
docker run
官方示例用法:
$ docker run -d -p 80:80 docker/getting-started
紧跟其后的第一个参数 -e
指定环境变量,--name
参数指定容器名称(TAG):
$ docker run -e "API_BASE_URL=m.coding.net" --name d_nginx_d5343399 hub.aliyun.com/sdet_dev/app:d_nginx_d5343399
执行 docker run
后,可以执行 docker ps
查看正在运行的容器(container),第一列为容器编号(CONTAINER ID、NAMES)。
docker ps
命令等效于 docker container ls
:
- 添加
-a
选项可查看所有的容器,包括启动失败、未在运行的。 - 添加
-q
选项可只查看第一列容器编号,不显示其他列信息。 - 添加
--no-trunc
不截断输出,可以查看完整不截断的 COMMAND。
$ docker help ps
Usage: docker ps [OPTIONS]
List containers
Options:
-a, --all Show all containers (default shows just running)
--no-trunc Don't truncate output
-q, --quiet Only display container IDs
exec
docker exec
命令在指定容器内执行命令:
$ docker exec -it [CONTAINER_ID] shell_command
docker help exec
查看帮助:
$ docker help exec
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
Options:
-d, --detach Detached mode: run command in the background
--detach-keys string Override the key sequence for detaching a container
-e, --env list Set environment variables
--env-file list Read in a file of environment variables
-i, --interactive Keep STDIN open even if not attached
--privileged Give extended privileges to the command
-t, --tty Allocate a pseudo-TTY
-u, --user string Username or UID (format: <name|uid>[:<group|gid>])
-w, --workdir string Working directory inside the container
启动镜像后,docker exec 执行容器中的命令:
# 或者 docker start 0.0.0.19-79945b77
$ docker start 417284a642ef
417284a642ef
# --no-trunc 查看详情
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
417284a642ef hub.aliyun.com/sdet_dev/app:0.0.0.19-79945b77 "/usr/share/nginx/ht…" 24 minutes ago Up 3 minutes 80/tcp 0.0.0.19-79945b77
docker exec -it TAG COMMAND
将在运行中标签为TAG的容器中执行COMMAND命令。
docker exec -it /bin/bash
将在当前终端为指定容器开启一个虚拟的交互式TTY(Shell Prompt for container)。
如果镜像内没有安装 /bin/bash,可以尝试 /bin/sh。
# 进入运行容器的shell prompt
# 或者 docker exec -it 0.0.0.19-79945b77 /bin/bash
$ docker exec -it 417284a642ef /bin/bash
# 过滤匹配 main.dart 文件
$ ls /usr/share/nginx/html | grep 'main.dart'
main.dart.79945b77.js
main.dart.js.map
# 可执行 cat、more 等命令查看具体文件内容
相关参考:
stop/start
- 可执行
docker restart CONTAINER_ID(CONTAINER_NAME)
重新启动指定容器。 - 也可执行
docker stop CONTAINER_ID(CONTAINER_NAME)
停止或执行docker kill CONTAINER_ID(CONTAINER_NAME)
强杀,然后执行docker start
重新启动运行。
可用 CONTAINER_ID、NAME 作为参数。
rm
docker rm CONTAINER ID
or docker rm CONTAINER NAME
移除指定容器。
$ docker help rm
Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
Options:
-f, --force Force the removal of a running container (uses SIGKILL)
-l, --link Remove the specified link
-v, --volumes Remove anonymous volumes associated with the container
rmi
docker rmi = docker image rm
$ docker rmi REPOSITORY:TAG
# or
$ docker rmi IMAGE_ID
注意:如果之前启动过某个镜像,通过 docker ps -a 检查,需要先执行 docker rm
移除 container,然后才能执行 docker rmi
移除镜像。
docker 制作镜像
基于 Dockerfile 进行 docker build 编译构建、运行调试本地镜像。
在 编译机集成flutter 中,考虑基于基础镜像 hub.aliyun.com/qcidocker/qci_base:latest
构建制作docker镜像。
Dockerfile
- Dockerfile reference
- Best practices for writing Dockerfiles
- 使用Dockerfile构建自己的镜像
- Docker 从入门到实践 - 使用 Dockerfile 定制镜像
基于 qci_base:latest 制作集成了 flutterSDK 的镜像 hub.aliyun.com/fantasy/qci_flutter:2.10.3,示例 Dockerfile 如下:
# FROM 指定基础镜像
FROM hub.aliyun.com/qcidocker/qci_base:latest
# docker build 的选项 --build-arg 指定该参数
ARG flutter_version
# 将 flutter_version 设置到环境变量(ENV)
ENV FLUTTER_VERSION=$flutter_version
# 设定环境变量(flutter install directory)
ENV FLUTTER_HOME=/usr/local/flutter
# RUN 执行 git clone 命令下载 flutter 到 FLUTTER_HOME
RUN git clone -b $FLUTTER_VERSION https://github.com/flutter/flutter.git $FLUTTER_HOME
# 设置 flutter bin 到环境变量
ENV PATH ${FLUTTER_HOME}/bin:${PATH}
# 设置 flutter PUB 代理
ENV PUB_HOSTED_URL=https://pub.flutter-io.cn
ENV FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
# 执行 flutter 检查命令
RUN flutter doctor
# 打印 flutter 信息
RUN flutter --version
docker build
在 Dockerfile 所在目录,执行 docker build
命令构建docker镜像:
其中
-t
指定镜像 TAG 名称。
docker build -t "qci_docker_flutter" .
=> => naming to docker.io/library/qci_docker_flutter
也可通过选项 --build-arg
选项指定参数 ARG flutter_version
:
docker build -t "qci_docker_flutter" --build-arg flutter_version=2.10.3 .
以下为流水线构建推送镜像步骤 Job log 中的完整命令:
docker build --pull . -t hub.aliyun.com/sdet_dev/app:0.0.1.103-95d7452f --file /data/__qci/root-workspaces/__qci-pipeline-330799-1//app/scripts/docker/Dockerfile
docker run
利用 build 命令打包构建镜像后,可以执行 docker image ls
命令,检查本地构建生成的镜像。
执行 docker run
命令可以运行本地打包的镜像,通过 --name
参数指定:
留意上一步 docer build 命令生成的 docker.io 本地路径。
docker run -P --name qci_docker_flutter docker.io/library/qci_docker_flutter
docker run 命令创建容器时,可通过 -P
选项或 -p
参数选项,指定宿主到容器的端口映射:
-P
: 容器内部端口随机映射到主机的高端口;-p port_host:port_docker
: 指定容器内部端口 port_docker 映射到指定的主机端口 port_host。
查看运行镜像的 CONTAINER ID,默认映射到宿主主机的 55000 端口:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
41c23aa6fd38 qci_docker_flutter "/docker-entrypoint.…" 26 seconds ago Up 25 seconds 0.0.0.0:55000->80/tcp qci_docker_flutter
浏览器输入链接 http://127.0.0.1:55000,即可访问 docker 镜像里运行的 nginx web 服务。
docker push
本地 build 构建的仓库,经过 run 本地调试确认没问题后,可考虑将镜像推送上远程镜像仓库,可以给 docker build 命令的 -t
选项指定为远端 Hub 仓库标签:
docker build -t hub.aliyun.com/org/fantasy/qci_docker_flutter --build-arg flutter_version=2.10.3 .
在 http://hub.aliyun.com/org/ 上组织新建项目仓库 fantasy
,然后执行 docker push 推送到 Hub 远端仓库:
docker push hub.aliyun.com/org/fantasy/qci_docker_flutter:2.10.3
本地构建push的仓库镜像,后续本地运行不用再pull,只需指定名称和仓库镜像即可。
docker run --name qci_docker_flutter hub.aliyun.com/org/fantasy/qci_docker_flutter:2.10.3
refs
了解微服务: 什么是微服务
了解虚拟化:VM、KVM
了解容器:容器编排、Kubernetes、Docker
Kubernetes中文社区 | 中文文档