Docker基础
# docker 基础
# 是什么
Docker 是一个开源的平台,主要用于开发、运输和运行应用程序。它使用容器技术,将应用程序及其依赖环境打包在一个独立的、轻量级的容器中,从而确保应用程序在任何环境中都能一致运行。Docker 解决了“在我电脑上没问题”的问题,使得开发人员能够更高效地构建、测试和部署应用程序。
# Docker 的主要组件
Docker Engine: 这是 Docker 的核心组件,负责创建和管理容器。它包含三个部分:
- 服务器(Docker Daemon):负责管理容器和镜像。
- REST API:用于与 Docker Daemon 进行通信。
- 客户端(CLI):命令行工具,用于与 Docker Daemon 交互。
Docker 镜像(Images): 只读模板,用于创建容器。镜像可以通过 Dockerfile 定义,包含了应用程序和运行所需的所有依赖。
Docker 容器(Containers): 由镜像实例化而来,是一个轻量级、独立的可执行包。每个容器包含一个完整的软件运行环境,包括代码、运行时、系统工具、系统库等。
Docker 仓库(Repositories): 存储和分发镜像的地方。常用的公共仓库是 Docker Hub,用户也可以创建私有仓库。
# Docker 的优点
- 一致的运行环境: 确保应用在不同环境下的运行一致性。
- 高效的资源利用: 容器共享主机的内核,启动速度快,资源开销小。
- 便捷的部署和扩展: 通过容器化,可以轻松部署和扩展应用。
- 强大的生态系统: 拥有丰富的工具和社区支持。
# 使用 Docker 的基本步骤
- 安装 Docker: 在开发或生产环境中安装 Docker。
- 创建 Dockerfile: 定义应用程序及其依赖的镜像。
- 构建镜像: 使用
docker build命令构建镜像。 - 运行容器: 使用
docker run命令运行容器。 - 管理容器: 使用
docker ps查看运行中的容器,使用docker stop停止容器等。
如果你对 Docker 感兴趣,可以进一步学习其高级特性,如 Docker Compose、Docker Swarm 等,以更好地管理和编排容器化应用。
# 为什么
使用 Docker 有很多优势,特别是在现代软件开发和运维过程中,主要原因包括:
# 1. 一致的开发和生产环境
Docker 容器可以包含应用程序及其所有依赖项,确保应用程序在任何环境(如开发、测试、生产)中的运行行为一致。这解决了“在我电脑上可以运行,但在服务器上不行”的问题。
# 2. 高效的资源利用
Docker 容器是轻量级的,因为它们共享主机操作系统的内核,而不需要像虚拟机那样每个实例都运行一个完整的操作系统。这使得容器的启动速度更快、资源开销更小。
# 3. 便捷的部署和扩展
Docker 容器的启动速度非常快,可以瞬时扩展应用程序的实例数量。Docker 的镜像提供了标准化的部署包,使得应用的部署和扩展变得非常简单。
# 4. 隔离性和安全性
每个容器在其独立的环境中运行,与其他容器和主机系统隔离。这种隔离性有助于提高安全性,因为容器之间的相互影响被最小化了。
# 5. 简化的持续集成和持续交付(CI/CD)
Docker 可以与 CI/CD 工具(如 Jenkins、GitLab CI 等)集成,实现自动化构建、测试和部署流程。Docker 镜像可以作为 CI/CD 流程中的标准化单元,使得整个流程更加稳定和可靠。
# 6. 易于版本控制和回滚
Docker 镜像可以版本化,允许开发人员轻松地回滚到之前的版本。这对于处理生产环境中的紧急问题非常有用。
# 7. 强大的生态系统和社区支持
Docker 具有丰富的工具生态系统和强大的社区支持。无论是 Docker Hub 上的公共镜像资源,还是第三方的管理工具和插件,开发者都能找到所需的资源和支持。
# 8. 微服务架构的支持
Docker 非常适合于微服务架构,每个服务都可以运行在独立的容器中,这使得服务的部署、扩展和管理更加灵活和高效。
# 示例场景
开发环境一致性: 开发团队可以使用相同的 Docker 镜像进行开发、测试和部署,确保环境一致,减少“环境差异”导致的问题。
自动化测试: 在 CI/CD 流程中,使用 Docker 容器运行自动化测试,可以确保每次测试在相同的环境中进行,提高测试的可靠性和准确性。
快速部署和扩展: 在高流量时期,使用 Docker 可以快速扩展应用的实例,满足高并发的需求;在流量下降时,又可以快速缩减实例数量,节约资源。
Docker 已经成为现代软件开发和运维中不可或缺的工具,通过其高效的资源利用、便捷的部署和强大的生态系统,极大地提高了开发和运维的效率。
# 怎么做
# 安装Docker docker-compose
下载docker官方社区源或者阿里源(选一个就行)
wget
https://download.docker.com/linux/centos/docker-ce.repo -O
/etc/yum.repos.d/docker-ce.repo
wget https://mirrors.aliyun.com/docker-
ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-
ce.repo
2
3
4
5
6
7
安装docker-ce
yum clean all
yum install docker-ce -y
systemctl start docker
systemctl enable docker
systemctl status docker
2
3
4
5
# docker 远程连接
可以将client与Server进行分离,实现远程docker连接。为了实现它, 就需要 对docker daemon进行相应的配置
docker -H 容器宿主机IP version
如何配置
- 关闭docker daemon守护进程
systemctl stop docker - 编辑docker daemon配置文件
vim /etc/docker/daemon.json
{
"hosts":
["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"]
}
2
3
4
netstat -ntlup | grep :2375 ls /var/run/docker.sock
docker daemon默认侦听使用的是unix格式,侦听文件:
UNIX:///run/docker.sock,添加tcp://0.0.0.0:2375可实现远程管理
- 添加/etc/docker/daemon.json后会导致docker daemon无法启动, 请先 修改如下文件内容,修改前 vim /usr/lib/systemd/system/docker.service
[Service]
Type=notify
# the default is not to use systemd for cgroups because
the delegate issues still
# exists and systemd currently does not support the cgroup
feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --
containerd=/run/containerd/containerd.sock
2
3
4
5
6
7
8
9
修改后:
[Service]
Type=notify
# the default is not to use systemd for cgroups because
the delegate issues still
# exists and systemd currently does not support the cgroup
feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd
2
3
4
5
6
7
8
- 重启docker daemon
systemctl restart docker - 连接远程docker
docker -H 容器宿主机IP version
# 创建Dockerfile
Dockerfile关键字
FROM(指定基础镜像)
MAINTAINER(镜像创建者信息)
RUN(运行命令)
CMD(设置container启动时执行的操作)
- 如果容器镜像中有此命令,启动容器时,不要手动让容器执行其他命令
ENTRYPOINT(设置容器启动时执行的操作)
USER(设置容器启动时的用户)
EXPOSE(指定容器需要映射到宿主机器的端口)
ENV(设置环境变量)
ADD(从src复制文件到container的dest路径)
VOLUME(挂载容器的目录)
WORKDIR(切换目录)
# 案例一: 创建一个简单的web应用
# RUN CMD ENTRYPOINT指令的区别
在 Dockerfile 中,CMD 和 RUN 是两个非常重要但用途不同的指令。它们的主要区别如下:
# RUN 指令
- 用途:
RUN指令用于在构建镜像时执行命令。通常用于安装软件包、配置系统等。 - 执行时机:
RUN指令在构建镜像过程中执行,每条RUN指令都会在镜像中创建一个新的层(layer)。 - 示例:
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y python3 python3-pip RUN pip3 install flask1
2
3
4
# CMD 指令
- 用途:
CMD指令用于指定容器启动时要运行的默认命令。每个 Dockerfile 只能有一个CMD指令,如果定义了多个,只有最后一个会生效。 - 执行时机:
CMD指令在容器启动时执行,即当你运行docker run命令启动容器时。 - 示例:
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y python3 python3-pip RUN pip3 install flask COPY . /app WORKDIR /app CMD ["python3", "app.py"]1
2
3
4
5
6
7
8
9
# 主要区别
执行阶段:
RUN: 在镜像构建时执行。CMD: 在容器启动时执行。
作用对象:
RUN: 用于设置镜像的状态,安装软件、配置环境等。CMD: 用于设置容器启动时的默认命令。
覆盖行为:
RUN: 每条指令都会在镜像中创建一个新的层。CMD: 可以被docker run命令行参数覆盖。例如,如果你在docker run命令中提供了一个命令,这个命令会覆盖CMD指令。
# 补充说明
- ENTRYPOINT:
- 类似于
CMD,但不能被docker run命令行参数覆盖。ENTRYPOINT指定容器启动时要运行的主命令,CMD通常用来提供默认参数。 - 例如:
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y curl ENTRYPOINT ["curl"] CMD ["http://example.com"]1
2
3
4
5
6
- 类似于
在这个例子中,如果你运行 docker run <image>,默认会执行 curl http://example.com。但是如果你运行 docker run <image> http://another-example.com,则会执行 curl http://another-example.com。
总结来说,RUN 用于构建镜像时执行命令,而 CMD 用于指定容器启动时的默认命令。两者在使用时有着不同的语境和目的。
# docker build 镜像
docker build 命令有许多参数,可以帮助你自定义构建过程。以下是一些常用参数及其用途:
# 常用参数
-t, --tag- 用于给镜像打标签(命名)。
- 示例:
docker build -t my-python-app:latest .1
-f, --file- 指定使用的 Dockerfile 文件(默认是当前目录中的
Dockerfile)。 - 示例:
docker build -f path/to/Dockerfile .1
- 指定使用的 Dockerfile 文件(默认是当前目录中的
--build-arg- 传递构建参数,可以在 Dockerfile 中使用
ARG指令访问这些参数。 - 示例:
docker build --build-arg HTTP_PROXY=http://proxy.example.com .1
- 传递构建参数,可以在 Dockerfile 中使用
--no-cache- 禁用缓存,强制重新构建所有步骤。
- 示例:
docker build --no-cache -t my-python-app .1
--pull- 尝试在构建镜像时拉取最新的基础镜像。
- 示例:
docker build --pull -t my-python-app .1
--rm- 在成功构建镜像后删除中间容器(默认行为)。
- 示例:
docker build --rm -t my-python-app .1
--force-rm- 在构建镜像过程中始终删除中间容器,无论构建是否成功。
- 示例:
docker build --force-rm -t my-python-app .1
-m, --memory- 设置构建过程中使用的最大内存。
- 示例:
docker build -m 512m -t my-python-app .1
--cpu-shares- 设置构建过程中使用的 CPU 份额。
- 示例:
docker build --cpu-shares 1024 -t my-python-app .1
--network- 设置构建过程中使用的网络模式(默认是
default)。 - 示例:
docker build --network host -t my-python-app .1
- 设置构建过程中使用的网络模式(默认是
--progress- 设置进度输出样式,选项包括
auto、plain和tty。 - 示例:
docker build --progress plain -t my-python-app .1
- 设置进度输出样式,选项包括
-f, --file- 参数用于指定 Dockerfile 文件的位置。默认情况下,docker build 命令会在当前目录中查找名为 Dockerfile 的文件。如果你的 Dockerfile 文件有不同的名称或位于其他位置,你可以使用 -f 参数来指定
- 示例:
docker build -f Dockerfile.dev -t my-python-app:dev .1
# 综合示例
以下是一个综合示例,展示如何使用多个参数:
docker build -f Dockerfile.dev \
--build-arg HTTP_PROXY=http://proxy.example.com \
--no-cache \
--pull \
--rm \
-m 1g \
--cpu-shares 2048 \
--network host \
--progress tty \
-t my-python-app:dev .
2
3
4
5
6
7
8
9
10
这个命令使用 Dockerfile.dev 文件构建镜像,设置了 HTTP 代理,禁用了缓存,强制拉取最新的基础镜像,限制最大内存为 1GB,设置 CPU 份额为 2048,使用主机网络模式,并且设置进度输出样式为 tty,最终将镜像标记为 my-python-app:dev。
这些参数可以根据具体需求进行调整和组合,以优化构建过程和镜像配置。如果有任何特定问题或进一步的需求,请告诉我!
# 管理容器
管理 Docker 容器涉及多种命令,这些命令允许你创建、启动、停止、重启、删除和检查容器的状态。以下是常用的 Docker 容器管理命令及其说明:
# 1. 创建和启动容器
docker run:创建并启动一个新的容器。docker run -d -p 80:80 --name my-container nginx1-d:在后台运行容器。-p 80:80:将容器的 80 端口映射到主机的 80 端口。--name my-container:为容器命名。nginx:使用 nginx 镜像。
# 2. 查看容器
docker ps:显示当前正在运行的容器。docker ps1docker ps -a:显示所有容器,包括已停止的。docker ps -a1
# 3. 停止和启动容器
docker stop:停止一个运行中的容器。docker stop my-container1docker start:启动一个已停止的容器。docker start my-container1docker restart:重启一个容器。docker restart my-container1
# 4. 暂停和恢复容器
docker pause:暂停一个容器中的所有进程。docker pause my-container1docker unpause:恢复一个暂停的容器中的所有进程。docker unpause my-container1
# 5. 删除容器
docker rm:删除一个已停止的容器。docker rm my-container1docker rm -f:强制删除一个运行中的容器。docker rm -f my-container1
# 6. 查看容器日志
docker logs:查看容器的日志输出。docker logs my-container1-f:跟随日志输出。--tail:查看日志的最后几行。
docker logs -f --tail 10 my-container1
# 7. 进入容器
docker exec:在运行中的容器中执行命令。docker exec -it my-container /bin/bash1-it:以交互模式运行,并分配一个伪终端。/bin/bash:在容器中启动 Bash shell。
# 8. 获取容器信息
docker inspect:查看容器的详细信息。docker inspect my-container1docker stats:实时查看容器的资源使用情况。docker stats my-container1
# 9. 网络和端口管理
docker port:查看容器的端口映射。docker port my-container1
# 10. 拷贝文件
docker cp:在主机和容器之间复制文件或目录。docker cp my-container:/path/to/file /host/path1或
docker cp /host/path my-container:/path/to/file1
除了前面提到的基础容器管理命令,Docker 还有一些其他高级和辅助管理命令,这些命令帮助你更深入地管理和操作容器及其资源。以下是一些常用的其他 Docker 管理命令:
# 11. 容器资源限制
docker update:更新一个或多个容器的资源限制。docker update --memory 512m --cpu-shares 512 my-container1
# 12. 查看容器资源使用情况
docker top:显示容器中运行的进程信息。docker top my-container1
# 13. 保存和加载容器
docker commit:将容器的当前状态保存为一个新的镜像。docker commit my-container my-new-image1docker export:将容器的文件系统导出为一个 tar 归档文件。docker export my-container > my-container.tar1docker import:从一个 tar 归档文件中创建一个镜像。docker import my-container.tar my-imported-image1
# 14. 镜像管理
docker images:列出本地镜像。docker images1docker rmi:删除一个或多个镜像。docker rmi my-image1docker tag:为镜像添加一个新的标签。docker tag my-image my-repo/my-image:latest1docker push:将镜像推送到镜像仓库。docker push my-repo/my-image:latest1docker pull:从镜像仓库拉取镜像。docker pull my-repo/my-image:latest1
# 15. 网络管理
docker network ls:列出所有网络。docker network ls1docker network create:创建一个新的网络。docker network create my-network1docker network connect:将一个容器连接到一个网络。docker network connect my-network my-container1docker network disconnect:将一个容器从一个网络断开。docker network disconnect my-network my-container1docker network inspect:查看网络的详细信息。docker network inspect my-network1docker network rm:删除一个网络。docker network rm my-network1
# 16. 数据卷管理
docker volume ls:列出所有数据卷。docker volume ls1docker volume create:创建一个新的数据卷。docker volume create my-volume1docker volume inspect:查看数据卷的详细信息。docker volume inspect my-volume1docker volume rm:删除一个数据卷。docker volume rm my-volume1
# 17. 系统信息和调试
docker info:显示 Docker 系统的详细信息。docker info1docker version:显示 Docker 的版本信息。docker version1
# 18. 清理系统
docker system prune:删除所有停止的容器、未使用的网络、未悬挂的镜像和构建缓存。docker system prune -a1
# 19. 事件监控
docker events:实时监控 Docker 守护进程的事件。docker events1
# 20. 配置管理
docker config:管理 Docker swarm 模式下的配置。创建配置:
echo "my-config-data" | docker config create my-config -1列出配置:
docker config ls1删除配置:
docker config rm my-config1
# docker容器网络
# 本地网络
# bridge 桥接(默认)
所有容器连接到桥,就可以使用外网,使用NAT让容器可以访问外网
[root@bogon ~]# ip a s
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
group default
link/ether 02:42:0d:52:fa:0a brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:dff:fe52:fa0a/64 scope link
valid_lft forever preferred_lft forever
#所有容器连接到此桥,IP地址都是172.17.0.0/16
#启动docker服务后出现
[root@bogon ~]# brctl show
bridge name bridge id STP enabled interfaces
br-5ca493f64e19 8000.02429cb0e393 no
docker0 8000.02420d52fa0a no
[root@bogon ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
93283dec7d39 bridge bridge local
#使用--network选择完成对容器网络的选择
[root@bogon ~]# docker run -d --network bridge smartgodocker/centos-nginx:v1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
每一台docker host上的docker0所在网段完全一样
# host 宿主机
所有的容器与docker host在同一网络中,可以让容器访问,甚至可以让外网主机访问容器中的服务
[root@bogon ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
51ab732381e8 host host local
2
3
使用--network选择容器运行的网络
[root@bogon ~]# docker run -it --network host centos:latest /bin/bash
[root@bogon /]# ip a s
bash: ip: command not found
[root@bogon /]# yum -y install iproute
#安装完成后,查看IP地址,发现其使用了docker host地址
#好处在于方便访问
#坏处在多容器同时运行一种服务,端口冲突
#仅在测试环境中使用
2
3
4
5
6
7
8
# none
容器仅与lo网卡,不能与外界连接,在高级应用中会使用到
[root@bogon ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
93283dec7d39 bridge bridge local
5ca493f64e19 harbor_harbor bridge local
51ab732381e8 host host local
4b7fd7698bec none null local
[root@bogon ~]# docker run -it --network none centos:latest
[root@8159e9d168ab /]# ip a s
#无法验证
2
3
4
5
6
7
8
9
# 容器网络
容器间共享同一个网络命名空间,实现容器间数据传输
# 跨主机容器间网络
# 实现跨主机容器间通信的工具
- Pipework
- Flannel
- Weave
- Open V Switch OVS
- Calico