🐳Docker Basic(Chinese)
一、Doker快速使用 Link to heading
1.1 构建一个容器 Link to heading
拉取并使用docker的ubuntu镜像构建一个交互式的容器。
sudo docker run --name containerName -i -t ubuntu /bin/bash
参数解释:
``–name`是对于容器的命名
-i
保证容器的STDIN开启,保证持续的标准输入;
-t
为docker为容器分配一个tty终端
ubuntu
提供的是镜像名,先从本机查找之后,若无则去dockerHub上查找
/bin/bash
告知容器需要运行的命令
1.2 关闭容器与查看 Link to heading
在容器内键入exit
可以退出容器,之后在宿主机上可以通过使用
docker ps -a
来查看所拥有的全部容器。
1.3 启动并附着到容器 Link to heading
当知道容器的名字或者uuid的时候可以使用
sudo docker start containerName
sudo docker start UUID
来重新运行容器,重新运行的容器会沿用docker run
时候的命令,此时我们可以使用
sudo docker attach containerName
重新进入容器的会话。
1.4 使用非交互的守护式容器 Link to heading
有时候需要长期运行的容器,并不需要交互式会话,这时候我们会选择使用守护式容器(daemonized container)
sudo docker run --name containerName -d ubuntu /bin/sh
参数解释:
-d
将容器放在后台运行
1.5 查看守护式容器信息 Link to heading
对于在后台运行的守护式容器,我们可以获取容器的日志。
sudo docker logs -f containerName
参数解释:
-f
跟踪式运行
在运行容器的时候可以选用不同的日志驱动,常见的有
- json-file(默认)
- syslog:禁用docker log命令,并将所有日志输出都重定向到syslog。
- none:禁用一切日志
另外也可以通过使用docker top name
来查看到容器内的进程,可以使用docker stats name
来查看容器内部的硬件统计信息。
1.6 在守护式容器内部运行新的进程 Link to heading
在docker1.3之后可以使用docker exec
命令在容器内部额外启动新的进程
sudo docker exec -d containerName command
参数解释:
-d
表示在后台运行
command
是需要的命令
或者使用如下命令来启动前端的程序
sudo docker exec -i -t containerName command
1.7 守护式容器的关闭与重启 Link to heading
对于后台运行的守护式容器,可以使用docker stop containerName
发送SIGTERM信号进行停止。
而对于快速停止则可以使用docker kill
命令发送SIGKILL信号。
容器有可能因为某种错误而停止,可以通过在run的时候进行标记,来使其自动重启。
sudo docker run --name containerName --restrat=always -i -t ubuntu /bin/bash
这个属性具有两种标价,可以使用always来设置为自动重启,也可以使用
on-failure:n
中的n来指定最多重启次数。
1.8 删除容器 Link to heading
当容器已经不在使用的时候,可以通过rm命令
sudo docker rm -f containerName
参数解释:
使用f可以无需关闭容器强行删除,不然则需要在删除容器前先关闭当前的容器。
删除所有容器需要多个命令的组合,如下:
sudo docker rm `sudo docker ps -a -q`
在ps命令中,可以使用
-a
获得所有的容器,而-q
的标志使得这条命令只返回id表
二、Docker的镜像与容器 Link to heading
2.1 基本概念介绍 Link to heading
Docker镜像是由文件系统叠加而成,最底端是一个引导文件系统(bootfs)。接下来第二层是root文件系统(rootfs),这可以是一种或者多种操作系统。接下来docker会使用联合加载(union mount)的技术在root文件系统层上加载更多的只读系统,将各层文件系统叠加到一起。
这样的文件系统就是docker的镜像,最底下是一个基础镜像,而最上面会叠加一个读写文件系统,我们的程序会在这上面运行。使用的机制是写时复制,当修改一个文件的时候,会从底层复制这个读写层,在对其修改后隐藏下面的层。
2.2 管理镜像 Link to heading
可以使用sudo docker images
来列出当前所拥有的全部镜像,也可以使用
sudo docker images imageName
来查看本地同一个镜像名,不同版本(tag)的镜像。
镜像可以从仓库下载,默认的仓库会保存在Docker公司的Registry服务(Docker hub)下。每一个仓库都可以存放很多镜像,如Ubuntu仓库中会保存很多版本的镜像。
Docker Hub中有两种类型的仓库,分别是用户仓库(user repository)和顶层仓库(top-level repository)
用户仓库:userName/repositoryName
顶层仓库:Name
对于镜像文件,可以在使用run
之前使用docker拉取相应的镜像文件
sudo docker pull image:tag
参数解释
tag是image的版本,都在image的仓库之中。
2.3 查找镜像 Link to heading
我们可以通过使用search命令查找,所有可用的公共镜像。
sudo docker search imageName
这个命令会在docker上查找所有包含这个名字的镜像,我们可以拉去这些镜像并用其创建容器。
2.4 构建镜像 Link to heading
我们修改、更新和、管理镜像提供了两种方法。
- 使用
docker commit
命令(不推荐) - 使用
docker build
命令和dockerfile文件
在使用commit
命令的时候,我们先启动容器,做自己需要的更改退出容器,之后可运行
sudo docker commit -m "informations" -a "author" id repositoryName/imageName:tag
参数解释:
id:容器的标识符
-m
:指定新创建的镜像的提交信息
-a
:作者的信息repositoryName:选择的镜像仓库名称,通常为自己的用户名
imageName:镜像名
tag:标签名
注:这个命令提交的只是创建容器的镜像和容器当前状态的差别部分,使得更新十分轻量。
2.5 基于Dockerfile来构建镜像 Link to heading
使用基于DSL语法的dockerfile可以构建镜像,具有更高的重复性、透明性、幂等性。
2.5.1 快速尝试 Link to heading
首先可以创建如下的基础Dockerfile
# Version:0.0.1
From ubuntu
LABEL shenvinci maintainer="shenvinci@gmail.com"
RUN apt-get update && apt-get install -y nginx
EXPOSE 80
参数解释:
FROM
指定了所用的基础镜像
LABLE
可以告知镜像的作者以及邮箱
EXPOSE
可以指定应用程序使用容器的端口
在使用Dockfile构建镜像的时候,每一条指令都会创建一个新的镜像并提交,这样的操作逻辑即使在某一条失败而没有正常的结束,仍可以保留一个最后的镜像文件,可以用于调试。
默认情况下RUN
指令会使用命令包装器来执行,而对于不希望在Shell中运行的可以使用exec
格式来运行指令,这种方式运行使用一个数组来指定要运行的命令和每一个参数。
RUN ["apt-get","install","-y","nginx"]
当有dockerfile存在后,我们可以使用build命令来构建镜像文件。
docker build -t="repositoryName/imageName:tag" path
参数解释:
-t=
用于表示镜像的仓库名,镜像名以及标签
path
表示dockerfile所处的路径,这个路径也可以是远端仓库的位置
当使用构建的时候,dokerfile所处的上下文也会被传送到docker守护进程,如果有不想被传送的文件可以通过设置.dockerignore
文件来选择需要过滤匹配的文件。
2.5.2 Dockerfile的缓存逻辑 Link to heading
因为在构建镜像的过程中,每一个步骤都会被构建为单独的镜像层,当再次使用dockerfile进行构建的时候,就会从最新一次有发生更改的部分继续进行构建。如果需要忽略所有缓存,则可以使用--no-cache
命令来忽略所有缓存构建。
因为这种特性,我们通常选择相似的docker模板,这样就可以不必重新运行前面的指令来构建镜像,而对于需要刷新的部分,我们可以在之前插入环境变量语句,如
# Version:0.0.2
From ubuntu
LABEL shenvinci maintainer="shenvinci@gmail.com"
ENV REFRESHED_AT 2021-9-30
RUN apt-get update && apt-get install -y nginx
EXPOSE 80
参数解释
ENV
:设置了一个名为REFRESHED_AT的环境变量,指明了模板最新更新的时间,当更改时间后,后面的所有内容都会重新运行,使得包可以进行刷新。
2.5.3 查看与使用新的镜像 Link to heading
docker images repositoryName/imageName
docker history repositoryName/imageName
上面的第一个代码,可以查看自己构建的镜像的具体状况,而需要查看具体的构建全步骤过程,则可以使用下面的,查看到每一层的镜像文件以及相应的构建指令。
当我们使用这种自己构建的镜像运行时候,我们的run
命令需要加入新的内容
sudo docker run -d -p 127.0.0.1:8080:80 --name containerName repositoryName/imageName command
参数解释
-p
参数用于配置容器与宿主机的端口链接,如上述命令是把容器的80映射到宿主机127ip的8080端口上,当其中有参数被省略时,则会使用默认(随机)参数。当我们使用-P
的时候,会将容器的80绑定到一个宿主机随机端口,然后将dockerfile中EXPOSE指定的端口全部公开.
command
命令是直接在容器内运行的内容,通常用于打开需要的服务
我们可以使用docker ps -l
命令查看所有容器被映射的端口,也可以使用docker port uuid 80
查看这一容器80端口被映射到的宿主机端口位置。
2.6 Dockerfile指令 Link to heading
2.6.1 CMD Link to heading
CMD指令用于指定容器启动时运行的命令(而RUN指令的只是在被构建时候运行),通常的格式为
CMD ["/bin/bash","-l"]
Docker一直推荐使用数组来设置需要执行的命令。同时我们需要牢记docker run
命令会覆盖CMD指令,同时要知道再Dockerfile中只能指定一条CMD指令,如果指定了多条则只有最后一条会被运行。
2.6.2 ENTRYPOINT Link to heading
这个指令与CMD十分类似,而最大的区别在于其不会被命令中的指令覆盖
实际上所有的指令都会作为参数传入
ENTRYPOINT
中。
在使用这个指令的时候我们也会使用数组进行内容的传输
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
将这个命令,CMD
命令以及docker run
时选择的命令进行组合,可以得到默认参数的使用方法。
ENTRYPOINT ["/usr/sbin/nginx"]
CMD["-h"]
docker run -t -i repositoryName/imageName -g "daemon off;"
在默认情况下,会使用CMD命令中的-h参数,但在run的时候如果添加了新的参数,则会对其进行覆盖,以此实现默认参数的效果。
2.6.3 WORKDIR Link to heading
这个指令可以在容器内部设置一个工作目录(切换内部的路径),用于CMD
与ENTRYPOINT
的执行。
WORKDIR /opt/webapp
CMD command
我们为command指令设置了路径
我们可以在run的时候通过-w
来覆盖工作的目录。
2.6.4 ENV Link to heading
在镜像构建的过程中设置环境变量,这个环境变量可以在之后任何RUN指令中使用,就如同在命令前面指定了环境变量的前缀。
ENV RVM_PATH=/home/rvm TARGET_FIR=/opt/app
RUN gem install unicorn
WORKDIR $TARGET_FIR
参数解释:
设置了
RVM_PATH
与TARGET_FIR
两个环境变量,第一个可以为第二条RUN
指令提供前缀条件,变成如RVM_PATH=/home/rvm RUN gem install unicorn
而第二个则被用于提供了工作目录的位置。
注意:在Dockerfile中设置的环境变量都是在容器中具有持久化作用的,而如果只是在使用docker run
时候加入-e
来传递的环境变量则只在运行的时候有效。
2.6.5 USER Link to heading
指定这个镜像以什么用户去运行,可以通过指定用户名(或uid)以及组(或gid)来选择。如果不选择默认会使用root
USER user
USER user:group
USER uid
USER uid:gid
2.6.6 VOLUME Link to heading
用来向基于镜像创建的容器添加卷(可以存在于一个或者多个容器内的特定的目录),卷可以绕过联合文件系统并提供共享以及持久化的数据功能,卷的功能可以让我们**把数据、数据库或者其他内容添加到镜像而不是将内容提交到镜像。**通常用来测试容器和内部的应用程序代码。管理日志,处理内部数据库。
VOLUME ["/opt/project",/data]
参数解释:
为基于此镜像的任何容器创建了这两个挂载点。
2.6.7 ADD Link to heading
将构建环境下的文件和目录复制到镜像之中,需要指定源文件位置和目的文件位置两个参数。
ADD contentPath aimPath
参数解释:
contentPath
是上下文的文件,通过末尾的字符来判断是目录还是文件,如果以/
结尾的就被认为是目录。在处理本地文件的时候,当归档文件被指定为源文件的时候,docker会把文件自动解开。(以URL指定目前不行)
aimPath
是镜像内的目标位置,如果目录不存在的话,会自动创建这样的新目录,其模式为文件模式为0755。
ADD
指令会使得构建的缓存变得无效,当添加后,所有的后续指令都需要重新进行构建。
2.6.8 COPY Link to heading
与ADD
命令基本类似,但不会做文件提取以及解压等方面的内容,需要注意,所有的文件源路径都必须是在Dockerfile的相对文件夹下,不能复制这个目录以外其他目录的内容。
2.6.9 LABEL Link to heading
这个指令可以为docker添加元数据,以键值对的形式展现出来。
LABEL version="1.0" location="China" type="Web"
推荐将所有的元数据都放入一条LABEL指令中,防止构建过多的镜像层。
我们可以通过docker inspect repositoryName/imageName
来查看容器内部的标签。
2.6.10 STOPSIGNAL Link to heading
用于设置停止容器的时候发送什么系统调用信号给容器,这信号必须是内核系统调用表中合法的数字(9)或者SIGNAME格式中信号名称(如SIGKILL)。
2.6.11 ARG Link to heading
用来定义可以在docker build
命令运行的时候传递给构建运行的变量,在构建时候可以根据dockerfile中定义过的变量进行传递
ARG build
ARG webapp_user=user
参数解释
定义了两个变量,第二个给了一个默认值,接下来可以在使用
docker build --build-arg build=1234
这样的命令来添加参数
2.6.12 ONBUILD Link to heading
为当前的镜像添加触发器,当这个镜像被用作为其他镜像的基础镜像的时候,该镜像中的触发器会被执行。触发器会在下一个继承他的镜像的FORM
之后添加这些被触发的指令
ONBUILD ADD . /app/src
ONBUILD RUN cd /app
此处使用了两条命令,当有新的镜像Dockerfile继承当前的镜像时候,运行后回在FORM之后插入这两句话
注意:触发器只能被子镜像继承,当孙镜像运行时候则不会再进行继承。
2.7 删除自己的镜像 Link to heading
当我们不再需要一个镜像的时候,我们可以使用
sudo docker rmi repositoryName/imageName1 repositoryName/imageName2
来删除这个镜像,这一行为同时也会删除构建这个镜像的时候所产生的每一层镜像,后面也可以不断往后罗列镜像,这将删除这镜像列表里面全部的镜像。
2.8 Docker镜像的管理 Link to heading
我们可以把自己在本地构建完成的镜像推送到远程仓库(默认为DockerHub),通过使用
docker push repositoryName/imageName
就可以将自己的镜像上传至自己的远程仓库之中。
而除了这种方式,我们可以选择使用自动构建,这只需要将Github中含有Dockerfile文件的仓库链接到Docker Hub上,当我们向github推送时候,dockerhub也会自动更新(但这种方式就不可以使用docker push
来发布镜像)。
三、Docker实战操作 Link to heading
3.1 卷的挂载 Link to heading
有些时候外面不想把应用或者代码构建到镜像之中
- 同时对代码进行开发与测试
- 代码改动十分频繁,不想在开发过程中重构镜像
- 希望在多个容器之间共享代码
这时候我们就需要使用docker的卷挂在来实现,通过在运行容器的时候使用-v 宿主机目录:容器内目录:读写权限
来对本地与容器内的文件进行映射挂载。
docker run -d -p 80 --name web -v ./web:/var/www/html/website:ro repositoryName/imageName2 cmd
3.2 容器的链接 Link to heading
3.2.1Docker Networking Link to heading
Docker Networking允许用户创建自己的网络,容器可以通过这个网络来互相通信,接下来是一些常用的管理指令。
sudo docker network create name #创建一个桥接网络并命名为name
sudo docker network inspect name #查看这个网络的信息
sudo docker network ls # 查看当前系统中的所有网络
sudo docker network rm # 删除一个网络
当有网络后,我们在运行容器时候可以加上–net=name
的标识符,把容器加入指定的网络之中。在网络内部启动的容器,docker会感知到所有在这个网络下的容器,并把这些信息都通过到当前容器的/etc/hosts
文件把所有地址都保存到DNS之中。
在网络之中的任何容器的地址,都可以通过hostname.app
的形式被解析,当一个容器重启的时候,它们的IP地址也会被自动更新(即对容器底层的修改不会对程序的正常工作产生影响)
3.2.2 Docker链接 Link to heading
在使用run
对容器进行运行的时候,我们增加--link containerName:linkName
创建了客户联系,此时被运行的容器被称为客户容器,而另一个则是服务,我们为这个服务增加了linkName作为别名,这可以让我们一致的访问容器公开的信息,且无须关注底层容器的名字。
将容器连接在一起可以让客户容器任意访问另一个容器,而不用对外公开端口。
四、Docker编配和服务发现 Link to heading
4.1 Docker Compose Link to heading
Dockers Compose通常被用于简单的Docker容器编配使用YAML
文件定义一组需要启动的容器,以及容器运行时的属性,这些容器可以被称为是服务。我们可以很快的使用Compose来创建多容器应用栈。
安装:使用pip install -U docker-compose
可以进行最新版本的快速安装
当应用的镜像构建完成之后,我们可以使用Compose来创建需要的服务,并定义启动时候需要的属性,这些属性都会被放置与YAML
文件之中,样例:
web:
image : shenvinci/flask
command : python app.py
ports :
- "5000:5000"
volumes :
- .:/composeapp
links :
- redis
redis:
image : redis
参数解释:
开启了分别名为
web
与redis
的两个容器文件,并为其配置了相应的参数,Compose会使用这些参数生产多个容器并组成相应的容器栈。
当切换至有YAML
文件的目录下后,我们有一些常用的指令
docker-compose up -d # 在后台运行容器栈
docker-compose ps # 列出本地docker-compose.yml 文件中正在运行的所有服务
docker-compose stop # 停止正在运行的所有服务
docker-compose kill # 强制杀死正在运行中的服务
docker-compose rm # 删除docker-compose服务