为什么会有Doker
Doker 的出现解决了开发与运维之间的运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。
Docker与虚拟机对比
虚拟机 | Docker | |
---|---|---|
体积 | 大 | 小 |
启动速度 | 慢 | 快 |
- 传统虚拟机是在虚拟出一套完整的硬件,然后在其上运行完整的操作系统(各种cpu、内存网络额配置+各种软件),再在该系统上运行所需的进程。虚拟机的缺点资源占用多 、冗余步骤多、启动慢。
- Docker容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统虚拟机则是在硬件层面实现虚拟化。与传统的虚拟机相比,Docker优势体现为启动速度快、占用体积小。
- Dockers的每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。
为什么Docker比虚拟机运行的快
Docker不需要虚拟出硬件资源,在Docker上运行的容器其实是直接使用宿主机的硬件。所以在对内存与CPU等硬件的应用上拥有较大优势。Docker的内核就是宿主机的内核,不需要重新加载系统内核。
Docker安装
由于Docker是一个并非通用的容器工具,它需要依赖已存在并且在运行的Linux内核 ,因此Docker需要部署在Linux环境下。
组成Docker的三要素
- 镜像(image)
Docker镜像只是一个模板,一个镜像可以用来创建出多个容器。 - 容器(Container)
Docker利用容器运行出一个或者一组应用,应用或者服务就在容器运行,容器可以看出虚拟化出来的虚拟环境。容器提供了一个隔离、独立的运行环境,它可以被启动、运行、停止、删除。 - 仓库(Repository)
是集中存储镜像的地方,有点类似于pip仓库用于存放python的各种包。Docker的官方提供的仓库为Docker Hub,存放各种镜像模板。Docker的仓库分为私有(private)和公有仓库(plublic)。最大的公有仓库为**Docker Hub。国内的公开仓库有阿里云(需要自己去以下链接创建专属镜像仓库)、[Docker中国区官方](https://registry.docker-cn.com)、网易
Docker安装
我使用的Ubuntu Docker安装可以参考官方教程
https://docs.docker.com/engine/install/ubuntu/
查看Docker 是否安装成功
$ docker --version
Docker version 20.10.21, build baeda1f
Docker 测试运行(hello-world)
$ docker run hello-world
# 本地未找到hello-world镜像
Unable to find image 'hello-world:latest' locally
# 从仓库下载一个hello-world镜像
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:faa03e786c97f07ef34423fccceeec2398ec8a5759259f94d99078f264e9d7af
Status: Downloaded newer image for hello-world:latest
# 在容器运行hello-world
# 输出这段提示以后,hello world就会停止运行,容器自动终止。
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
Linux下Docker的常用命令
# 启动docker
systemctl start docker
# 停止docker
systemctl stop docker
# 重启docker
systemctl restart docker
# 查看docker状态
systemctl status docker
# 开机启动
systemctl enable docker
# 查看docker概要信息
docker info
# 查看docker总体帮助文档
docker --help
# 查看docker命令帮助文档
docker 具体命令 --help
Docker操作的常用命令
# 新建+启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS:
有些是一个减号,有些是两个减号
--name="容器新名字" 给容器指定一个名称;
-d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行);
-i:以交互模式运行容器,通常与 -t 同时使用;
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
也即启动交互式容器(前台有伪终端,等待交互);
-P: 随机端口映射,大写P
-p: 指定端口映射,小写p
# 例如---以交互式启动Ubuntu:
docker run -it ubuntu /bin/bash
# 其中放在镜像名后的是命令/bin/bash ,用于一个交互式 Shell
# 以后台守护启动Ubuntu
docker run -d ubuntu
# 查看当前所有正在运行的容器
docker ps [OPTIONS]
OPTIONS:
-a :列出当前所有正在运行的容器+历史上运行过的
-l :显示最近创建的容器。
-n:显示最近n个创建的容器。
-q :静默模式,只显示容器编号。
# 退出容器(有两个方式)
# 方式一(run进去容器,exit退出,容器停止)
exit
# 方式二(run进去容器,ctrl+p+q退出,容器不停止)
ctrl+p+q
# 启动已停止运行的容器
docker start 容器ID或者容器名
# 重启容器
docker restart 容器ID或者容器名
# 停止容器
docker stop 容器ID或者容器名
# 强制停止容器
docker kill 容器ID或容器名
# 删除已停止的容器
docker rm 容器ID
# 一次性删除多个容器实例
docker rm -f $(docker ps -a -q) 或 docker ps -a -q | xargs docker rm
# 查看容器日志
docker logs 容器ID
# 查看容器内运行的进程
docker top 容器ID
# 查看容器内部细节
docker inspect 容器ID
# 进入正在运行的容器并以命令行交互
docker exec -it 容器ID bashShell
# 重新进入
docker attach 容器ID
注:exec 与 attach的区别
exec 是在容器中打开新的终端,并且可以启动新的进程用exit退出,不会导致容器的停止。(推荐)
attach 直接进入容器启动命令的终端,不会启动新的进程用exit退出,会导致容器的停止。
# 从容器内拷贝文件到主机上(容器→主机)
docker cp 容器ID:容器内路径 目的主机路径
eg: docker cp aca3c6bdca27:/usr/local/mycopy/test.txt /tmp/test_1.txt
# 导出容器
export 导出容器的内容留作为一个tar归档文件
eg: docker export aca3c6bdca27 > test.tar.gz
# 导入容器
import 从tar包中的内容创建一个新的文件系统再导入为镜像
eg: cat test.tar.gz | docker import - test/ubuntu:2.1
常用命令总结
attach Attach to a running container # 当前 shell 下 attach 连接指定运行镜像
build Build an image from a Dockerfile # 通过 Dockerfile 定制镜像
commit Create a new image from a container changes # 提交当前容器为新的镜像
cp Copy files/folders from the containers filesystem to the host path #从容器中拷贝指定文件或者目录到宿主机中
create Create a new container # 创建一个新的容器,同 run,但不启动容器
diff Inspect changes on a container's filesystem # 查看 docker 容器变化
events Get real time events from the server # 从 docker 服务获取容器实时事件
exec Run a command in an existing container # 在已存在的容器上运行命令
export Stream the contents of a container as a tar archive # 导出容器的内容流作为一个 tar 归档文件[对应 import ]
history Show the history of an image # 展示一个镜像形成历史
images List images # 列出系统当前镜像
import Create a new filesystem image from the contents of a tarball # 从tar包中的内容创建一个新的文件系统映像[对应export]
info Display system-wide information # 显示系统相关信息
inspect Return low-level information on a container # 查看容器详细信息
kill Kill a running container # kill 指定 docker 容器
load Load an image from a tar archive # 从一个 tar 包中加载一个镜像[对应 save]
login Register or Login to the docker registry server # 注册或者登陆一个 docker 源服务器
logout Log out from a Docker registry server # 从当前 Docker registry 退出
logs Fetch the logs of a container # 输出当前容器日志信息
port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT # 查看映射端口对应的容器内部源端口
pause Pause all processes within a container # 暂停容器
ps List containers # 列出容器列表
pull Pull an image or a repository from the docker registry server # 从docker镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to the docker registry server # 推送指定镜像或者库镜像至docker源服务器
restart Restart a running container # 重启运行的容器
rm Remove one or more containers # 移除一个或者多个容器
rmi Remove one or more images # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
run Run a command in a new container # 创建一个新的容器并运行一个命令
save Save an image to a tar archive # 保存一个镜像为一个 tar 包[对应 load]
search Search for an image on the Docker Hub # 在 docker hub 中搜索镜像
start Start a stopped containers # 启动容器
stop Stop a running containers # 停止容器
tag Tag an image into a repository # 给源中镜像打标签
top Lookup the running processes of a container # 查看容器中运行的进程信息
unpause Unpause a paused container # 取消暂停容器
version Show the docker version information # 查看 docker 版本号
wait Block until a container stops, then print its exit code # 截取容器停止时的退出状态值
Docker镜像commit
# docker commit的作用是提交一个容器作为一个镜像
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
eg: docker commit -m="ubuntu_test" -a="xiaolin" aca3c6bdca27 ubuntu_test:1.1
Docker容器挂载主机目录
# 挂载
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
--privileged=true命令是为了扩大容器的权限解决挂载目录没有权限的问题,即使容器内的root拥有真正的root权限,否则,容器内的root只是外部的一个普通用户权限。
# 查看是否挂在成功
docker inspect 容器ID
"Mounts": [
{
"Type": "bind",
# 宿主机卷
"Source": "/tmp/DockerData",
# 容器卷
"Destination": "/tmp/hostData",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
注:
1 docker修改,主机同步获得
2 主机修改,docker同步获得
3 docker容器stop,主机修改,docker容器重启数据自动同步。
# 权限管理
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
注:
容器与宿主机之间数据共享默认就是rw权限
# 只读模式
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
# 卷的继承和共享
docker run -it --privileged=true -v /mydocker/u:/tmp --name u1 ubuntu
docker run -it --privileged=true --volumes-from u1 --name u2 ubuntu
DockerFile
DockerFile是用来构建Docker镜像的文本文件,其有一条条的构建镜像的命令和参数组成的脚本文件。
官方文档:https://docs.docker.com/engine/reference/builder/
DockerFile构建大致可以划分为三步骤:
- 编写Dockerfile文件
- docker build命令构建镜像
- docker run 镜像运行容器实例
Docker执行Dockerfile的大致流程:
- docker从基础镜像创建一个容器
- 顺序执行指令并对容器作出修改
- 执行类似docker commit的操作提交一个新的镜像层
- docker再基于刚提交的镜像运行一个新容器
- 执行dockerfile中的下一条指令直到所有指令都执行完成
注:
- 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
2.指令按照从上到下,顺序执行
3.#表示注释
4.每条指令都会创建一个新的镜像层并对镜像进行提交
DockerFile常用保留字指令
FROM | 基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from | From ubuntu |
MAINTAINER | 镜像维护者的姓名和邮箱地址 | MAINITAINER xiaolin |
RUN | 容器构建时需要运行的命令 shell格式/exec格式 | RUN<命令行> eg:RUN yum -y install vim RUN [“可执行文件”,“参数1”,“参数二”] eg:RUN [“./test.py”,“dev”,“offline”] |
EXPOSE | 当前容器对外暴露出的端口 | EXPOSE 80 |
WORKDIR | 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点 | |
USER | 指定该镜像以什么样的用户去执行,如果都不指定,默认是root | |
ENV | 用来在构建镜像过程中设置环境变量 | ENV MY_PATH /usr/mytest这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;也可以在其它指令中直接使用这些环境变量,egWORKDIR $MY_PATH |
ADD | 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包 | |
COPY | 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置 | |
VOLUME | 容器数据卷,用于数据保存和持久化工作 | |
CMD | 指定容器启动后的要干的事情 | Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换 |
ENTRYPOINT | 也是用来指定一个容器启动时要运行的命令,类似于 CMD 指令,但是ENTRYPOINT不会被docker run后面的命令覆盖, | |
而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序 | ENTRYPOINT[ “<executeable>” , “<param1>” , “<param2>”,…] | 在执行docker run的时候可以指定 ENTRYPOINT 运行所需的参数。如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。 |
注:
ENTRYPOINT可以和CMD一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,他两个组合会变<ENTRYPOINT><CMD>
FROM python:3.6 # 指定拉取镜像版本
ENV PYTHONUNBUFFERED 1 # 不缓冲stdin、stdout和stderr,直接把输出重定向到文件
MAINITAINER xiaolin # 指定作者
RUN mkdri /code # 运行的linux命令
WORKDIR /code # 指定项目工作根路径
ADD . /code/ # 将宿主机文件复制到镜像中
COPY dj.conf /etc/nginx/conf.d # docker内部文件拷贝
VOLUME ["/data1","/data2"] # 将宿主机文件夹挂载到容器中
EXPOSE 8080 # 暴露端口
CMD ["sh","/code/start.sh"] # 容器启动时要运行的命令
CMD ["python", "manage.py", "runserver", "0:8000"]
Docker网络
网络模式
- bridge模式:使用–network bridge指定,默认使用docker0
- host模式:使用–network host指定
- none模式:使用–network none指定
- container模式:使用–network container:NAME或者容器ID指定
# 查看网络
docker network ls
# 查看网络源数据
docker network inspect XXX网络名字
# 删除网络
docker network rm XXX网络名字
补充虚悬镜像
虚悬镜像是指·仓库名、标签都是的镜像,俗称dangling image
# 查看
docker image ls -f dangling=true
# 删除
docker image prune
# 虚悬镜像已经失去存在价值,可以删除