Docker使用教程
1 Docker概述
1.1 简介
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。
Docker出现的背景:
- 开发和运维两套环境,而环境配置十分麻烦。
如在Windows上开发,要发布到Linux上运行。Docker给以上问题提出了解决方案:
Java — Jar(环境)—打包项目带上环境(镜像)—Docker仓库(应用商店)—下载镜像—直接运行 - Docker的思想来自于集装箱,核心思想:隔离。
即将应用打包装箱,每个箱子是互相隔离的,可以将服务器利用到极致。
虚拟机 | Docker |
---|---|
linux centos原生镜像(一个电脑) | 隔离镜像(最核心的环境 +jdk +mysql等) |
需要开启多个虚拟机 | 运行镜像就可以了 |
几GB | 几MB |
文章图片
1.2 Docker的应用场景
- Web 应用的自动化打包和发布。
- 自动化测试和持续集成、发布。
- 在服务型环境中部署和调整数据库或其他的后台应用。
- 从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。
Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker,您可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方法来快速交付,测试和部署代码,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。
(1)快速,一致地交付您的应用程序
Docker 允许开发人员使用您提供的应用程序或服务的本地容器在标准化环境中工作,从而简化了开发的生命周期。
容器非常适合持续集成和持续交付(CI / CD)工作流程,请考虑以下示例方案:
- 您的开发人员在本地编写代码,并使用 Docker 容器与同事共享他们的工作。
- 他们使用 Docker 将其应用程序推送到测试环境中,并执行自动或手动测试。
- 当开发人员发现错误时,他们可以在开发环境中对其进行修复,然后将其重新部署到测试环境中,以进行测试和验证。
- 测试完成后,将修补程序推送给生产环境,就像将更新的镜像推送到生产环境一样简单。
Docker 是基于容器的平台,允许高度可移植的工作负载。Docker 容器可以在开发人员的本机上,数据中心的物理或虚拟机上,云服务上或混合环境中运行。
Docker 的可移植性和轻量级的特性,还可以使您轻松地完成动态管理的工作负担,并根据业务需求指示,实时扩展或拆除应用程序和服务。
(3)在同一硬件上运行更多工作负载
Docker 轻巧快速。它为基于虚拟机管理程序的虚拟机提供了可行、经济、高效的替代方案,因此您可以利用更多的计算能力来实现业务目标。Docker 非常适合于高密度环境以及中小型部署,而您可以用更少的资源做更多的事情。
2 Docker架构 Docker 包括三个基本概念:
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 centos:latest 就包含了完整的一套centos最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
文章图片
文章图片
概论 | 说明 |
---|---|
Docker daemon | Docker 守护进程 ( dockerd ) 侦听 Docker API 请求并管理 Docker 对象,例如images、containers、networks和volumes。守护进程还可以与其他守护进程通信以管理 Docker 服务。 |
Docker client | Docker 客户端 ( docker ) 是大多数 Docker 用户与 Docker 交互的主要方式。当您使用诸如docker run 之类的命令时,客户端会将这些命令发送到dockerd ,从而执行它们。该docker 命令使用 Docker API。Docker 客户端可以与多个守护进程通信。 |
Docker registries | Docker注册中心,用于存储Docker Images,Docker Hub(https://hub.docker.com)是官方的注册中心提供了庞大的Images供使用,Docker默认配置为在Docker Hub上查找Images,也可自定义注册中心来加快下载(如阿里云的)。 当使用 docker pull 或docker run 命令时,所需的映像将从配置的注册中心中提取。当使用docker push 命令时,映像会被推送到配置的注册中心中。 |
Docker Images | Docker 镜像是用于创建 Docker 容器的模板,比如 centos系统。 |
Docker Containers | 容器是独立运行的一个或一组应用,是镜像运行时的实体。 |
Docker Machine | Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。 |
- 操作系统要求:CentOS7 及以上版本
- 卸载旧版本。较旧的 Docker 版本称为 docker 或 docker-engine
$ sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
var/lib/docker/
下包含的images、 containers、volumes 和 networks将被保留。Docker 引擎包当前叫docker-ce
(docker社区版)。
在新主机上首次安装 Docker Engine 之前,您需要设置 Docker 存储库。之后,您可以从存储库安装和更新 Docker。
- 安装
yum-utils
包(提供了yum-config-manager
实用程序)
#安装yum-utils包 $ sudo yum install -y yum-utils
- 设置稳定仓库(选择其中一个,建议选择阿里云仓库)
#设置官方仓库地址(慢) $ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo#设置国内阿里云的仓库地址 $ sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo#设置清华大学仓库地址 $ sudo yum-config-manager --add-repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
- 安装 Docker Engine-Community
#列出仓库中可用版本 $ yum list docker-ce --showduplicates | sort -r#下载最新版本 $ sudo yum install docker-ce docker-ce-cli containerd.io#下载指定版本,如docker-ce版本3:20.10.6-3.el7,docker-ce-cli版本1:20.10.6-3.el7 $ sudo yum install docker-ce-3:20.10.6-3.el7 docker-ce-cli-1:20.10.6-3.el7 containerd.io
- 启动docker
$ sudo systemctl start docker
- 通过运行
hello-world
映像来验证是否正确安装了 Docker Engine-Community 。
$ sudo docker run hello-world
- 卸载Docker Engine、cli和containerd包
$ sudo yum remove docker-ce docker-ce-cli containerd.io
- 在你主机上的images、containers、volumes和 自定义配置文件不会自动删除,可通过以下命令去删除
$ sudo rm -rf /var/lib/docker $ sudo rm -rf /var/lib/containerd
[root@swarm-85 ~]# dockerUsage:docker [OPTIONS] COMMANDA self-sufficient runtime for containersOptions:
--config stringLocation of client config files (default "/root/.docker")
-c, --context stringName of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")
-D, --debugEnable debug mode
-H, --host listDaemon socket(s) to connect to
-l, --log-level stringSet the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
--tlsUse TLS;
implied by --tlsverify
--tlscacert stringTrust certs signed only by this CA (default "/root/.docker/ca.pem")
--tlscert stringPath to TLS certificate file (default "/root/.docker/cert.pem")
--tlskey stringPath to TLS key file (default "/root/.docker/key.pem")
--tlsverifyUse TLS and verify the remote
-v, --versionPrint version information and quitManagement Commands:
app*Docker App (Docker Inc., v0.9.1-beta3)
builderManage builds
buildx*Build with BuildKit (Docker Inc., v0.5.1-docker)
configManage Docker configs
containerManage containers
contextManage contexts
imageManage images
manifestManage Docker image manifests and manifest lists
networkManage networks
nodeManage Swarm nodes
pluginManage plugins
scan*Docker Scan (Docker Inc.)
secretManage Docker secrets
serviceManage services
stackManage Docker stacks
swarmManage Swarm
systemManage Docker
trustManage trust on Docker images
volumeManage volumesCommands:
attachAttach local standard input, output, and error streams to a running container
build从Dockerfile构建一个镜像
commitCreate a new image from a container's changes
cpCopy files/folders between a container and the local filesystem
createCreate a new container
diffInspect changes to files or directories on a container's filesystem
eventsGet real time events from the server
execRun a command in a running container
exportExport a container's filesystem as a tar archive
historyShow the history of an image
imagesList images
importImport the contents from a tarball to create a filesystem image
infoDisplay system-wide information
inspectReturn low-level information on Docker objects
killKill one or more running containers
loadLoad an image from a tar archive or STDIN
loginLog in to a Docker registry
logoutLog out from a Docker registry
logsFetch the logs of a container
pausePause all processes within one or more containers
portList port mappings or a specific mapping for the container
psList containers
pullPull an image or a repository from a registry
pushPush an image or a repository to a registry
renameRename a container
restartRestart one or more containers
rmRemove one or more containers
rmiRemove one or more images
runRun a command in a new container
saveSave one or more images to a tar archive (streamed to STDOUT by default)
searchSearch the Docker Hub for images
startStart one or more stopped containers
statsDisplay a live stream of container(s) resource usage statistics
stopStop one or more running containers
tagCreate a tag TARGET_IMAGE that refers to SOURCE_IMAGE
topDisplay the running processes of a container
unpauseUnpause all processes within one or more containers
updateUpdate configuration of one or more containers
versionShow the Docker version information
waitBlock until one or more containers stop, then print their exit codes
文章图片
4.1 Docker Images
当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。
- 1、管理和使用本地 Docker 主机镜像
- 2、创建镜像
$ docker images
REPOSITORYTAGIMAGE IDCREATEDSIZE
hello-worldlatestd1165f2212342 months ago13.3kB
- **REPOSITORY:**表示镜像的仓库源(名称)
- **TAG:**镜像的标签(版本)
- **IMAGE ID:**镜像ID
- **CREATED:**镜像创建时间
- **SIZE:**镜像大小
docker search
命令来搜索镜像#从注册中心查找httpd镜像
$ docker search httpd
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5AiIhst8-1622888322570)(C:\Users\yutyi\AppData\Roaming\Typora\typora-user-images\image-20210602223924387.png)]
- NAME: 镜像仓库源的名称
- DESCRIPTION: 镜像的描述
- OFFICIAL: 是否 docker 官方发布
- STARS: 类似 Github 里面的 star,表示点赞、喜欢的意思
- AUTOMATED: 自动构建。
docker pull
命令来下载它。$ docker pull httpd
Using default tag: latest
latest: Pulling from library/httpd
69692152171a: Pull complete
7284b4e0cc7b: Pull complete
3678b2d55ccd: Pull complete
aeb67982a725: Pull complete
06954f8169fd: Pull complete
Digest: sha256:48bae0ac5d0d75168f1c1282c0eb21b43302cb1b5c5dc9fa3b4a758ccfb36fe9
Status: Downloaded newer image for httpd:latest
docker.io/library/httpd:latest
run:运行镜像 运行上面拉取的httpd镜像
#-d后台运行镜像
$ docker run -d httpd
rmi:删除镜像
#删除未运行的镜像,-f可删除正在运行的镜像
$ docker rmi httpd
commit/build:创建镜像 当我们从 docker 镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改:
- 1、从已经创建的容器中更新镜像,并且提交这个镜像
- 2、使用 Dockerfile 指令来创建一个新的镜像
- 更新镜像之前,我们需要使用镜像来创建一个容器
$ docker run -tid centos /bin/bash
- 进入容器并更新
#进入容器 $ docker exec -it 6eea07909632 /bin/bash#更新centos内核并退出 [root@6eea07909632 /]# yum update --skip-broken [root@6eea07909632 /]# exit exit
- 提交容器
#将当前更新的容器提交生成新的镜像, # -m 提交的描述信息 # -a 指定镜像作者 [root@swarm-85 ~]# docker commit -m="core update" -a="yut" 6eea07909632 centos:update sha256:ec0925217a5637118d555467987b32872b4885eee265f1d55f120df4f439ff9b
docker build
, 从零开始来创建一个新的镜像。为此,我们需要创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像$ vim Dockerfile
FROMcentos:6.7
MAINTAINERyut "yut@gmail.com"RUN/bin/echo 'root:123456' |chpasswd
RUNuseradd yut
RUN/bin/echo 'yut:123456' |chpasswd
RUN/bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE22
EXPOSE80
CMD/usr/sbin/sshd -D
- FROM:指定使用的镜像源
- MAINTAINER:指定维护者名称 邮件
- RUN:指定docker在镜像内执行的命令
- EXPOSE:指定暴露的端口
#-t 指定创建的镜像名
#. Dockerfile的路径
$ docker build -t yut/centos:6.7 .
运行新生成的镜像并查看
#可以发现新生成的镜像已经包含yut用户
$ docker run -it yut/centos:6.7 /bin/bash
[root@3f2c3e1c3e45 /]# id yut
uid=500(yut) gid=500(yut) groups=500(yut)
tag:为镜像添加一个新的标签 IMAGE ID一样,表示是同一个镜像
$ docker tag yut/centos:6.7 centos/yut:dev
$ docker images
REPOSITORYTAGIMAGE IDCREATEDSIZE
yut/centos6.7fde06d35a56f6 minutes ago191MB
centos/yutdevfde06d35a56f6 minutes ago191MB
4.2 Docker Containers
run:启动容器 案例一 运行一个centos镜像,如果没有则去仓库下载
# -i:交互式操作
# -t:开启一个终端
# centos:最新的centos镜像,等同于centos:latest
# /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
$ docker run -ti centos /bin/bash
退出终端
exit# 从容器中退回主机
CTRL+Q+P# 容器不停止退出
案例二 docker容器中运行一个 Python Flask 应用来运行一个web应用
#1.拉取镜像
$ docker pull training/webapp#2.运行镜像,
# -d 后台运行
# -P 将容器内部使用的网络端口随机映射到我们使用的主机上
$ docker run -d -P training/webapp python app.py#3.查看运行的容器,0.0.0.0:49154->5000/tcp:Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 32769 上
[root@swarm-85 ~]# docker ps
CONTAINER IDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
8cc812142c11training/webapp"python app.py"4 seconds agoUp 4 seconds0.0.0.0:49154->5000/tcp, :::49154->5000/tcpboring_khorana
我们也可以指定映射端口
#-p 指定映射端口,主机端口6000
$ docker run -d -p 6000:5000 training/webapp python app.py
#也可绑定主机
$ docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py
#也可以指定tcp/udp
$ docker run -d -p 127.0.0.1:5002:5000/udp training/webapp python app.py
文章图片
ps:查看容器
#查看容器,-a参数是查看正在运行+已停止的
$ docker ps -a
CONTAINER IDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
93a6357a681chttpd"httpd-foreground"30 seconds agoExited (0) 21 seconds agosweet_allen
port:查看网络端口 通过
docker ps
命令可以查看到容器的端口映射,docker
还提供了另一个快捷方式 docker port
,使用 docker port 可以查看指定 (ID 或者名字)容器的某个确定端口映射到宿主机的端口号。#查看指定容器端口映射
$ docker port 5ca222c3d6e3
5000/tcp -> 0.0.0.0:6000
5000/tcp -> :::6000#查看指定容器指定端口的映射
$ docker port 5ca222c3d6e3 5000
0.0.0.0:6000
:::6000
logs:查看容器日志
#-f: 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。
$ docker logs -f 5ca222c3d6e3
top:查看容器内部运行的进程
$ docker top 8cc812142c11
UIDPIDPPIDCSTIMETTYTIMECMD
root18571835009:35?00:00:00python app.py
stats: 查看容器的运行状态
#类似Linux top命令
$ docker stats
start:启动已停止的容器
$ docker start 93a6357a681c
stop:停止容器
$ docker stop 93a6357a681c
restart:重启容器
#停止的容器也可以用该命令启动
$ docker restart 93a6357a681c
attach/exec:进入容器 在使用
-d
参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:- docker attach
- docker exec:推荐大家使用
docker exec
命令,因为此退出容器终端,不会导致容器的停止。
- attach命令
#使用attach命令进入后再exit退出,容器会停止 $ docker attach 6eea07909632 [root@6eea07909632 /]# exit exit
- exec命令
#使用exec命令进入后再exit退出,容器不会停止 $ docker exec -it 6eea07909632 /bin/bash
#第一种写法
$ docker export -o centos.tar 6eea07909632
#第二种写法
$ docker export 6eea07909632 > centos.tar
import:导入容器快照 从容器快照文件中再导入为镜像
#第一种写法
$ cat centos.tar | docker import - centos:v1
#第二种写法
$ docker import centos.tar centos:v2
rm:删除容器
#-f强制删除正在运行的容器
$ docker rm -f 93a6357a681c#删除所有处于终止状态的容器
$ docker container prune
4.3 Docker容器互联
docker run -p
端口映射并不是唯一把 docker 连接到另一个容器的方法,docker 有一个连接系统允许将多个容器连接在一起,共享连接信息。docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息。- 创建一个桥接网络
#-d 指定 Docker 网络类型,有 bridge、overlay $ docker network create -d bridge test-net
- 运行centos镜像并连接到新建的网络
#运行生成二个容器 $ docker run -itd --name centos-test --network test-net centos /bin/bash $ docker run -itd --name centos-test1 --network test-net centos /bin/bash
- 进入centos-test容器ping centos-test1容器,测试网络
$ docker exec -it 6ba2473abf30 bin/bash [root@6ba2473abf30 /]# ping centos-test1 PING centos-test1 (172.18.0.3) 56(84) bytes of data. 64 bytes from centos-test1.test-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.054 ms 64 bytes from centos-test1.test-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.040 ms 64 bytes from centos-test1.test-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.039 ms ...
Docker Hub:在 https://hub.docker.com 免费注册一个 Docker 账号。
阿里云:在https://cr.console.aliyun.com/cn-hangzhou/instances 免费注册一个容器镜像服务。
login:登录 登录需要输入用户名和密码,登录成功后,我们就可以从 docker hub 上拉取自己账号下的全部镜像。
# 登录阿里云Docker Registry,-u 用户名
$ docker login --username=yutao_stru**** registry.cn-hangzhou.aliyuncs.com
push:将本地镜像推送到个人仓库 用户登录后,可以通过
docker push
命令将镜像推送到Registry。#添加镜像的标签
$ docker tag centos:update registry.cn-hangzhou.aliyuncs.com/yuchangtao/test:dev
#推送
$ docker push registry.cn-hangzhou.aliyuncs.com/yuchangtao/test:dev
logout:登出
$ docker logout
5 Docker镜像详解
文章图片
Docker镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,如代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包docker镜像,就可以直接运行。
5.1 UnionFS(联合文件系统)
- 联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
- 特性:一次同时加载多个文件系统,但从外面看起来只能看到一个文件系统。联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker的镜像实际由一层一层的文件系统组成:
- bootfs(boot file system)主要包含bootloader和kernel。bootloader主要是引导加载kernel,完成后整个内核就都在内存中了。此时内存的使用权已由bootfs转交给内核,系统卸载bootfs。可以被不同的Linux发行版公用。
- rootfs(root file system),包含典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同操作系统发行版(Ubuntu,Centos等)。因为底层直接用宿主机的kernel,rootfs只包含最基本的命令,工具和程序就可以了。
- 分层理解
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。容器在启动时会在镜像最外层上建立一层可读写的容器层(R/W),而镜像层是只读的(R/O)。
【big|Docker使用教程】
文章图片
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[tag]# 编辑容器后提交容器成为一个新镜像
6 容器数据卷
文章图片
6.1 什么是容器数据卷?
为了实现数据持久化,使容器之间可以共享数据。可以将容器内的目录,挂载到宿主机上或其他容器内,实现同步和共享的操作。即使将容器删除,挂载到本地的数据卷也不会丢失。
6.2 使用容器数据卷
使用命令:
dokcer run -it -v 主机内目录:容器内目录 镜像名/id
将容器内目录挂载到主机内目录上,通过docker inspect命令查看该容器即可以看到挂载信息:
文章图片
建立挂载关系后,只要使用命令在主机内新建一个文件:
touch /home/mountdir/test.txt
就会在容器内的挂载目录下发现相同的文件(test.txt),从而实现了容器和主机的文件同步和共享:
文章图片
6.3 匿名挂载
docker run -d-v 容器内目录镜像名/id# 匿名挂载
匿名挂载后,使用
docker volume ls
命令查看所有挂载的卷:文章图片
每一个VOLUME NAME对应一个挂载的卷,由于挂载时未指定主机目录,因此无法直接找到目录。
6.4 具名挂载
docker run -d-v 卷名:容器内目录镜像名/id# 具名挂载
文章图片
可以发现挂载的卷:volume01,并通过docker volume inspect 卷名 命令找到主机内目录:
文章图片
所有docker容器内的卷,在未指定主机内目录时,都在:
/var/lib/docker/volumes/卷名/_data
下,可通过具名挂载可以方便的找到卷,因此广泛使用这种方式进行挂载。6.5 数据卷容器
文章图片
docker run -it --name container02 --volumes from container01 镜像名/id# 将两个容器进行挂载
子容器继承父容器的数据卷。
7 Docker Dockerfile 参考文档:https://docs.docker.com/engine/reference/builder/
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
7.1 构建过程
- 每个保留关键字(指令)都必须是大写字母
- 从上到下顺序执行
- “#” 表示注释
- 每一个指令都会创建提交一个新的镜像层并提交
FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html
b. 构建镜像
$ docker build -t nginx:v3 .
7.2 命令列表
命令 | 效果 | 命令 | 示例 |
---|---|---|---|
FROM | 定制的镜像都是基于 FROM 的基础镜像,如:centos | FROM <镜像名> | FROM centos |
MAINTAINER | 镜像作者+邮箱 | ||
RUN | 镜像构建的时候需要运行的命令,RUN 是在 docker build 时运行 |
shell格式:RUN <命令行命令> exec 格式:RUN [“可执行文件”, “参数1”, “参数2”] |
RUN ls / RUN ["./test.php", “dev”, “offline”] |
COPY | 复制指令,从上下文目录中复制文件或者目录到容器里指定路径 | COPY [–chown=:] <源路径1>… <目标路径> COPY [–chown=:] ["<源路径1>",… “<目标路径>”] |
|
ADD | ADD 指令和 COPY 的使用格式一致,自动解压压缩包 | ADD [–chown=:] <源路径1>… <目标路径> ADD [–chown=:] ["<源路径1>",… “<目标路径>”] |
|
CMD | 指定这个容器启动时要运行的命令,CMD 在docker run 时运行,CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。 |
CMD CMD ["<可执行文件或命令>","","",…] CMD ["","",…] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数 |
|
ENTRYPOINT | 类似于 CMD 指令,但其不会被docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。docker run 使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序。如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。 |
ENTRYPOINT ["","","",…] | FROM nginx ENTRYPOINT [“nginx”, “-c”] # 定参 CMD ["/etc/nginx/nginx.conf"] # 变参#运行 $ docker run nginx:test -c /etc/nginx/new.conf #容器内默认运行的命令 nginx -c /etc/nginx/nex.conf |
WORKDIR | 镜像工作目录(进入容器时的目录)指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存(WORKDIR 指定的工作目录,必须是提前创建好的)。 | WORKDIR <工作目录路径> | |
USER | 用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。 | USER <用户名>[:<用户组>] | |
VOLUME | 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。作用:1.避免重要的数据,因容器重启而丢失,这是非常致命的。2.避免容器不断变大。 | VOLUME ["<路径1>", “<路径2>”…] VOLUME <路径> |
|
EXPOSE | 暴露端口配置,仅仅只是声明端口。作用:1.帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。2.在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。 |
EXPOSE <端口1> [<端口2>…] | |
CMD/ENTRYPOINT | 指定这个容器启动时要运行的命令(CMD替代先前命令,ENTRYPOINT在先前命令后追加) | ||
COPY | 类似于ADD,将文件拷贝到镜像中 | ||
ENV | 构建时设置环境变量,在后续的指令中,就可以使用这个环境变量 | ENV ENV = =… |
|
ARG | 构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。 |
ARG <参数名>[=<默认值>] | |
HEALTHCHECK | 用于指定某个程序或者指令来监控 docker 容器服务的运行状态 | #设置检查容器健康状况的命令 HEALTHCHECK [选项] CMD <命令> #如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令 HEALTHCHECK NONE |
|
ONBUILD | 用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会被执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像FROM test-build ,这时使用新的 Dockerfile 构建镜像时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。 |
ONBUILD <其它指令> |
镜像分层优化 **注意:**Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:
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
如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。
上下文路径 . 上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。
注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。
COPY 复制指令,从上下文目录中复制文件或者目录到容器里指定路径
COPY [--chown=:] <源路径1>...<目标路径>
COPY [--chown=:] ["<源路径1>",..."<目标路径>"]
- [–chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。
- <源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则
- <目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建
- ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
- ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
docker run
的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。但是, 如果运行
docker run
时使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序。ENTRYPOINT ["","","",...]
优点:在执行
docker run
的时候可以指定 ENTRYPOINT 运行所需的参数。注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
案例:
FROM nginxENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
构建nginx:test镜像
- 不传参运行
#运行 $ docker run nginx:test #容器内默认运行的命令 nginx -c /etc/nginx/nginx.conf
- 传参运行
#运行 $ docker runnginx:test -c /etc/nginx/new.conf#容器内默认运行的命令 nginx -c /etc/nginx/nex.conf
通过命令
ip addr
查看本地ip地址,我们发现除了本机回环地址和阿里云的内网地址外,还多了一个网卡:docker0,这是Docker服务启动后自动生成的。文章图片
而如果后台运行一个tomcat容器并进入容器,同样使用
ip addr
命令,发现容器得到了一个新的网络:12: eth@if13,ip地址:172.17.0.2。这是Docker在容器启动时为其分配的。文章图片
思考一个问题:此时我们的linux主机可以ping通容器内部(172.17.0.2)吗?
文章图片
- linux可以ping通docker容器内部,因为docker0的ip地址为172.17.0.1,容器为172.17.0.2。
- 原理:我们每启动一个docker容器,docker就会给容器分配一个默认的可用ip,我们只要安装了docker,就会有一个网卡docker0(bridge)。网卡采用桥接模式,并使用veth-pair技术(veth-pair就是一堆虚拟设备接口,成对出现,一段连着协议,一段彼此相连,充当一个桥梁。)。
- 这时我们退出容器,回到主机再次观察主机的ip地址:
文章图片
我们惊奇地发现了一个新网络13: vethda1df4b@if12,对应容器内网络地址的12: eth0@if13。
- 容器和容器之间是可以互相ping通的:容器1→Docker0→容器2
文章图片
docker中的所有网络接口都是虚拟的 ,转发效率高。删除容器后,对应的网桥也随之删除。
8.2 --link
若编写一个微服务并连接数据库,如果数据库ip改变,如何根据容器名而不是ip访问容器?显然,直接使用容器名是无法ping通容器内部的:
文章图片
这时我们可以在容器启动命令中加入一个选项:–link,使得我们可以根据容器名来访问容器。
docker run -d -P --link 容器名/id 镜像名/id
文章图片
然而反向就不可以ping通,这是因为–link的本质是把需要连接的容器名/id写入启动容器的配置文件中,即增加了一个ip和容器名/id的映射:
文章图片
目前已经不建议使用这种方式。
8.3 自定义网络
我们使用命令:
docker network ls# 查看所有的docker网络
文章图片
docker中的网络模式有:
- bridge:桥接(docker默认)/
- none:不配置网络 /
- host:和宿主机共享网络
docker run
命令默认带有一个参数--net bridge
,此处的bridge指的就是docker0。如果我们不想使用docker0,那如何创建一个新的网络呢?docker network create --driver 网络模式 --subnet 子网ip --gateway 网关 网络名
文章图片
我们不仅在
docker network ls
命令下发现了这个新创建的网络newnet,还可以使用docker network inspect
命令查看其详细信息,包括了我们创建时定义的子网ip和网关:文章图片
只要两个容器启动时都通过 –net,选用了同一个已创建的网络,不同容器间即可通过ip地址或容器名/id连通:
文章图片
8.4 网络连通
文章图片
对于建立在不同网络下(docker0, newnet)的两个容器tomcat01和tomcat02,他们的网段不同,因此是无法彼此ping通容器内部的:
文章图片
这时我们需要通过
docker network connect
命令打通容器与网络之间的连接:#容器连接到该网络会分配ip地址
docker network connect 网络名 容器名/id
文章图片
这个功能类似于将一个容器赋予多个ip地址,同样可以用
docker network inspect
命令查看网络连通后,该网络的变化:文章图片
原本newnet网络中只含有tomcat02,现在增加了tomcat01,因此可以连通。
8.5 配置DNS
我们可以在宿主机的
/etc/docker/daemon.json
文件中增加以下内容来设置全部容器的 DNS:{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
设置后,启动容器的 DNS 会自动配置为 114.114.114.114 和 8.8.8.8。
配置完,需要重启 docker 才能生效。
查看容器的 DNS 是否生效可以使用以下命令,它会输出容器的 DNS 信息:
$ docker run -it --rmcentoscat etc/resolv.conf
如果只想在指定的容器设置 DNS,则可以使用以下命令:
$ docker run -it --rm -h host_centos --dns=114.114.114.114 --dns-search=test.com centos
参数说明:
-
--rm
:容器退出时自动清理容器内部的文件系统。
-
-h HOSTNAME 或者 --hostname=HOSTNAME
: 设定容器的主机名,它会被写到容器内的 /etc/hostname 和 /etc/hosts。
-
--dns=IP_ADDRESS
: 添加 DNS 服务器到容器的/etc/resolv.conf
中,让容器用这个服务器来解析所有不在/etc/hosts
中的主机名。
-
--dns-search=DOMAIN
: 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 host.example.com。
--dns
和 --dns-search
,Docker 会默认用宿主主机上的 /etc/resolv.conf
来配置容器的 DNS。9 Docker 编排工具 Docker三大编排工具:
Docker Compose
:是用来组装多容器应用的工具,可以在 Swarm集群中部署分布式应用。Docker Machine
(被Docker Desktop取代):是支持多平台安装Docker的工具,使用 Docker Machine,可以很方便地在笔记本、云平台及数据中心里安装Docker。Docker Swarm
:是Docker社区原生提供的容器集群管理工具。
Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
Compose 使用的三个步骤:
- 使用 Dockerfile 定义应用程序的环境。
- 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
- 最后,执行
docker-compose up
命令来启动并运行整个应用程序。
# yaml 配置实例
version: "3.9"# optional since v1.27.0
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
9.1.1 Compose安装 MacOS和Windows PC的 Docker 桌面版和 Docker Toolbox 已经包括 Compose 和其他 Docker 应用程序,因此不需要单独安装 Compose。Docker Compose 依赖 Docker Engine,以下是Linux的安装步骤:
#1.下载
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose#2.将可执行权限应用于二进制文件
$ chmod +x /usr/local/bin/docker-compose#3.测试是否安装成功
$ docker-compose --version
docker-compose version 1.29.2, build 5becea4c
9.1.2 Docker Compose使用 测试案例
- 创建测试目录
$ mkdir composetest $ cd composetest
- 在测试目录中创建
app.py
文件
import timeimport redis from flask import Flaskapp = Flask(__name__) cache = redis.Redis(host='redis', port=6379)def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5)@app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count)
- 在测试目录中创建
requirements.txt
文件
flask redis
- 在测试目录中创建
Dockerfile
文件
# syntax=docker/dockerfile:1 FROM python:3.7-alpine WORKDIR /code ENV FLASK_APP=app.py ENV FLASK_RUN_HOST=0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY requirements.txt requirements.txt RUN pip install -r requirements.txt EXPOSE 5000 COPY . . CMD ["flask", "run"]
- 在测试目录中创建
docker-compose.yml
文件
version: "3.9" services: web: build: . ports: - "5000:5000" redis: image: "redis:alpine"
- 使用compose命令启动
#-d 后台启动 docker-compose up -d
9.2 Docker Machine
Docker Machine 是一种可以让您在虚拟主机上安装 Docker 的工具,并可以使用 docker-machine 命令来管理主机。
Docker Machine 也可以集中管理所有的 docker 主机,比如快速的给 100 台服务器安装上 docker。当前已被Docker Desktop替代。
- 我有一个较旧的桌面系统,想在 Mac 或 Windows 上运行 Docker
文章图片
- 我想在远程系统上配置 Docker 主机
文章图片
9.3 Docker Desktop
Docker Desktop 是一款易于安装的应用程序,适用于您的 Mac 或 Windows 环境,使您能够构建和共享容器化应用程序和微服务。Docker Desktop包Docker Engine、Docker CLI Client、Docker Compose、Notary、Kubernetes和Credential Helper。
Docker Desktop的一些关键特征:
- 能够以多种语言和框架在任何云平台上容器化和共享任何应用程序
- 轻松安装和设置完整的 Docker 开发环境
- 包括最新版本的 Kubernetes
- 自动更新,让您保持最新状态和安全
- 在 Windows 上,能够在 Linux 和 Windows Server 环境之间切换以构建应用程序
- 使用本机 Windows Hyper-V 虚拟化实现快速可靠的性能
- 能够通过 Windows 机器上的 WSL 2 在 Linux 上本地工作
- 代码和数据的卷安装,包括文件更改通知和轻松访问本地主机网络上运行的容器
- 使用支持的 IDE 进行容器内开发和调试
简介 Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API,所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。
支持的工具包括但不限于以下各项:
- Dokku
- Docker Compose
- Docker Machine
- Jenkins
文章图片
Swarm命令
Command | Description |
---|---|
docker swarm ca | Display and rotate the root CA |
docker swarm init | Initialize a swarm |
docker swarm join | Join a swarm as a node and/or manager |
docker swarm join-token | Manage join tokens |
docker swarm leave | Leave the swarm |
docker swarm unlock | Unlock swarm |
docker swarm unlock-key | Manage the unlock key |
docker swarm update | Update the swarm |
[root@swarm-85 ~]# docker swarm init --advertise-addr 172.31.235.85
Swarm initialized: current node (lmekdd6kwd971b24mdala8gw8) is now a manager.To add a worker to this swarm, run the following command:docker swarm join --token SWMTKN-1-4tevaj5zg011v76s2j63tbpfxp3bo02hkej6d2j8kt8uo7gmdt-bv9ma9iw2vz5h4uqm3ek9zxvx 172.31.235.85:2377To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
join-token:获取加入swarm的令牌
#获取作为manager角色加入swarm的令牌
[root@swarm-85 ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:docker swarm join --token SWMTKN-1-4tevaj5zg011v76s2j63tbpfxp3bo02hkej6d2j8kt8uo7gmdt-b6nvaz2snckd9fngi6djpsdlp 172.31.235.85:2377
#获取作为worker角色加入swarm的令牌
[root@swarm-85 ~]# docker swarm join-token worker
To add a worker to this swarm, run the following command:docker swarm join --token SWMTKN-1-4tevaj5zg011v76s2j63tbpfxp3bo02hkej6d2j8kt8uo7gmdt-bv9ma9iw2vz5h4uqm3ek9zxvx 172.31.235.85:2377
join:加入swarm
#swarm-80主机作为worker角色加入swarm
[root@swarm-80 ~]# docker swarm join --token SWMTKN-1-4tevaj5zg011v76s2j63tbpfxp3bo02hkej6d2j8kt8uo7gmdt-bv9ma9iw2vz5h4uqm3ek9zxvx 172.31.235.85:2377
This node joined a swarm as a worker.#swarm-78主机作为worker角色加入swarm
[root@swarm-78 ~]# docker swarm join --token SWMTKN-1-4tevaj5zg011v76s2j63tbpfxp3bo02hkej6d2j8kt8uo7gmdt-bv9ma9iw2vz5h4uqm3ek9zxvx 172.31.235.85:2377
This node joined a swarm as a worker.#swarm-81主机作为manager角色加入swarm
[root@swarm-81 ~]# docker swarm join --token SWMTKN-1-4tevaj5zg011v76s2j63tbpfxp3bo02hkej6d2j8kt8uo7gmdt-b6nvaz2snckd9fngi6djpsdlp 172.31.235.85:2377
This node joined a swarm as a manager.
node ls:查看节点列表
[root@swarm-85 ~]# docker node ls
IDHOSTNAMESTATUSAVAILABILITYMANAGER STATUSENGINE VERSION
sn4ggriw0et6u1yacl2gcbzxkswarm-78ReadyActive20.10.7
8kjxe9jk9xh7m06hsbdgmwo36swarm-80ReadyActive20.10.7
lmekdd6kwd971b24mdala8gw8 *swarm-85ReadyActiveLeader20.10.7
y21tyjr9tbof2iyaqim9ijw3iswarm-81ReadyActiveReachable20.10.7
leave:离开swarm
[root@swarm-80 ~]# docker swarm leave
Node left the swarm.
扩缩容案例
docker run
和docker-compose up
都是单机操作;使用docker swarm
和docker service
管理集群,动态的创建、扩展、更新服务(灰度发布)。[root@swarm-85 ~]# docker serviceUsage:docker service COMMANDManage servicesCommands:
createCreate a new service
inspectDisplay detailed information on one or more services
logsFetch the logs of a service or task
lsList services
psList the tasks of one or more services
rmRemove one or more services
rollbackRevert changes to a service's configuration
scaleScale one or multiple replicated services
updateUpdate a service
测试一下:
#使用docker service create启动一个nginx容器
[root@swarm-85 ~]# docker service create -p 8888:80 --name my-nginx nginx
mfcy9mlsy08wi368a9xb6roj7
overall progress: 1 out of 1 tasks
1/1: running[==================================================>]
verify: Service converged #使用docker service ls查看服务列表
[root@swarm-85 ~]# docker service ls
IDNAMEMODEREPLICASIMAGEPORTS
mfcy9mlsy08wmy-nginxreplicated1/1nginx:latest*:8888->80/tcp#使用docker serice ps查看运行的一个或多个服务的任务列表
[root@swarm-85 ~]# docker service ps my-nginx
IDNAMEIMAGENODEDESIRED STATECURRENT STATEERRORPORTS
yqdbq9fwvq93my-nginx.1nginx:latestswarm-85RunningRunning 2 minutes ago
#使用docker service inspect查看一个或多个服务的详细信息
[root@swarm-85 ~]# docker service inspect mfcy9mlsy08w
扩容/缩容:
- 方式一:
#更新服务副本数 [root@swarm-85 ~]# docker service update --replicas 3 my-nginx my-nginx overall progress: 3 out of 3 tasks 1/3: running[==================================================>] 2/3: running[==================================================>] 3/3: running[==================================================>] verify: Service converged
- 方式二:
[root@swarm-85 ~]# docker service scale my-nginx=5 my-nginx scaled to 5 overall progress: 5 out of 5 tasks 1/5: running[==================================================>] 2/5: running[==================================================>] 3/5: running[==================================================>] 4/5: running[==================================================>] 5/5: running[==================================================>] verify: Service converged
$ docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问地址http://lcoalhost:8088
文章图片
可视化面板一般企业不会被使用,仅供个人测试使用
推荐阅读
- Docker|Docker之Dockerfile简介
- devops|GitLab+Jenkins+Harbor+Kubernetes构建Devops体系
- 常见的一些容器部署|CentOS7安装JDK8
- docker weave网络
- Linux学习及相关操作|Linux配置静态ip地址(CentOS7)(不踩坑)
- Hbase学习|hbase的安装配置过程(CentOS7)
- python从入门到实战|【Python编程】一、Python安装(Linux/Windows)与简介
- docker存储卷
- spark|莎士比亚统计最高的词频数 java,spark,rdd