Docker 的基本使用

HYF Lv3

引言

随着软件开发和部署的不断进步,开发者们需要一种能够确保应用程序在各种环境中一致运行的方法。传统的虚拟机虽然能够提供环境隔离,但其资源开销和启动时间较长,限制了开发和部署的效率。在这种背景下,Docker 作为一种轻量级的容器化技术应运而生。

Docker 提供了一种简便的方式来创建、部署和运行应用程序,它将应用程序及其依赖项打包在一个容器中,以确保在任何环境下都能一致运行。这种容器化技术不仅提高了开发和部署的效率,还大大减少了系统资源的消耗。

鲁迅先生说过,万物皆可容器。容器作为一个你可以不用,但一定要知道的技术,显然十分重要。本文将带你深入了解 Docker 的基本概念和使用方法。从 Docker的概念开始,我们将逐步介绍如何使用 Docker 镜像和容器,如何管理容器中的数据,以及如何利用 Docker Compose 进行多容器应用的编排。希望看完本篇文章,你将能够快速上手 Docker,并在实际项目中应用这一强大的工具。

'鲁迅先生'说

容器化的优点

一致性

容器包含了应用程序运行所需的所有依赖项,确保在任何环境中都能一致地运行,从而避免了“在我机器上可以运行”的问题

轻量级

容器比传统的虚拟机更加轻量级,因为它们共享主机操作系统的内核。这减少了启动时间和资源开销

隔离性

容器之间相互隔离,每个容器都有自己的文件系统、进程空间和网络接口,确保应用程序之间不会互相干扰

可移植性

容器可以在各种环境中运行,包括本地开发机器、数据中心的服务器和云平台。这使得应用程序从开发到生产的迁移变得更加容易和可靠

高效的资源利用

由于容器共享主机操作系统的内核,相比虚拟机的完整操作系统开销,容器的资源利用效率更高

快速部署

容器启动速度快,可以在几秒钟内启动一个容器,从而加快了开发、测试和部署的速度

版本控制和回滚

Docker 镜像支持版本控制,你可以轻松地管理不同版本的应用程序,并在需要时快速回滚到之前的版本

持续集成和持续部署(CI/CD)

容器化技术与 CI/CD 流程无缝集成,使得自动化构建、测试和部署变得更加容易

弹性和可伸缩性

容器可以快速创建和销毁,非常适合构建弹性和可伸缩的应用程序。你可以根据需要动态地调整容器的数量,以应对负载变化

简化的依赖管理

容器包含了所有运行时所需的依赖项,避免了依赖冲突和版本不兼容的问题

安全性

虽然容器与主机共享内核,但它们之间的隔离性依然很强。使用正确的安全配置,可以确保应用程序在隔离的环境中安全运行

什么是 Docker

关于这个问题,我们首先要了解一下 Docker 三要素:镜像(Image)、容器(Container)和仓库(Registry)。

仓库(Registry)

Docker 仓库是用于存储和分发 Docker 镜像的服务。Docker 官方提供了公共的 Docker Hub,此外还有其他第三方或私有的 Docker 仓库(如 Google Container RegistryAmazon ECR 等)。仓库的主要用途为集中管理和分发 Docker 镜像,使得镜像的分享和部署更加方便。

仓库的特性主要有以下三点:

镜像存储: 仓库用于存储不同版本的 Docker 镜像,可以是公共的也可以是私有的

镜像分发: 用户可以将镜像推送到仓库中,或者从仓库中拉取镜像,以便在不同的环境中使用

自动化构建: 一些仓库(如 Docker Hub)支持自动化构建功能,可以自动从代码仓库构建新的镜像版本

镜像 (Image)

Docker 镜像是一个轻量级、独立的、可执行的软件包,包含了运行应用程序所需的所有内容:代码、运行时、库、环境变量、配置文件等。镜像主要用于创建容器,每个镜像可以创建多个容器实例。

镜像的特性主要有以下三点:

只读: 镜像是不可变的、只读的文件系统,包含了应用程序的所有依赖项

分层结构: 镜像由一系列分层组成,每一层代表一个文件系统快照。镜像的分层结构使得镜像的构建、存储和传输更加高效

版本控制:通过标签(Tags)来管理不同版本的镜像。例如,myapp:latestmyapp:v1.0 表示同一应用程序的不同版本

容器 (Container)

Docker 容器是镜像的一个运行实例,它包含了应用程序及其所有依赖项,并在一个隔离的环境中运行。容器主要用于实际运行应用程序,可以根据需要启动、停止和销毁容器实例。

镜像的特性主要有以下三点:

轻量级: 容器共享宿主操作系统的内核,因此相比虚拟机更加轻量级,启动速度快,资源利用率高

隔离性: 每个容器运行在独立的进程空间中,拥有自己的文件系统、网络接口和资源限制,确保应用程序之间互不干扰

灵活性: 容器可以在任何支持 Docker 的环境中运行,使得应用程序的开发、测试和部署更加灵活和便捷

仓库——镜像——容器之间的关系

经过上述介绍,相信读者对 Docker 的概念也有一定的了解。是的,Docker 的三要素(镜像、容器和仓库)之间有着紧密的关系,构成了 Docker 生态系统的基础。以下是它们之间的关系和交互:
镜像(`Image`)与容器(`Container`)

创建关系:容器是由镜像创建的。每个容器都从一个特定的镜像启动,并运行在一个隔离的环境中。镜像可以视为一个蓝图,而容器则是这个蓝图的运行实例

依赖关系:容器依赖镜像来获取其文件系统和应用程序的所有依赖项。镜像中包含的代码、库、环境变量等都会在容器中运行时被使用

多实例:同一个镜像可以被多次使用来创建多个容器实例,这些容器可以独立运行,互不干扰

镜像(`Image`)与仓库(`Registry`)

存储关系:镜像存储在仓库中。仓库(如 Docker Hub)提供了一个集中化的存储位置,方便镜像的管理和分发

版本控制:仓库中存储的镜像可以有多个版本,通过标签(tags)来区分。不同版本的镜像可以存储在同一个仓库中,方便开发者管理和使用

推送与拉取:开发者可以将本地构建的镜像推送到仓库中(上传),也可以从仓库中拉取镜像到本地使用(下载)。这使得镜像可以在不同的环境之间迁移和共享

容器(`Container`)与仓库(`Registry`)

间接关系:容器本身并不直接与仓库交互,而是通过镜像与仓库间接关联。容器是由从仓库中拉取的镜像创建的。当然,容器也可以被导出成镜像,然后回归到镜像与仓库的关系

整体工作流程

构建镜像:开发者在本地使用 Dockerfile 定义应用程序的环境和依赖项,并构建出一个 Docker 镜像

推送镜像:将构建好的镜像推送到 Docker 仓库(如 Docker Hub),使其可以被共享和分发

拉取镜像:在需要运行应用程序的环境中,从仓库中拉取最新的镜像

创建容器:使用拉取的镜像创建并运行容器。容器运行时会使用镜像中定义的环境和依赖项

管理和更新:当应用程序需要更新时,开发者可以构建新的镜像版本,推送到仓库,并在目标环境中拉取并运行新的容器

使用 Docker

Docker 仓库

Docker 仓库主要有两种类型:公共仓库和私有仓库。每种类型的仓库都可以在不同的环境中使用。

例如官方提供的 Docker Hub,以及其他第三方提供的容器镜像存储服务和私有仓库解决方案就为公共仓库类型,公共仓库是开放给所有用户使用的仓库,任何人都可以从中拉取镜像,也可以将自己的镜像推送到公共仓库中,供其他人使用。

私有仓库只对授权用户开放,适用于企业内部使用,确保安全性和定制化管理,常见的有 Docker Hub 私有仓库、Azure Container RegistryAmazon ECRGoogle Container RegistryHarbor

Docker 仓库的核心动作为找(search)、推(push)以及拉(pull),例如以下命令:
1
2
3
4
5
6
7
8
9
# 
docker search redis

#
docker push [仓库名称/命名空间/镜像:版本号]

#
docker pull redis(:latest) # 拉取最新版本,可省略版本号
docker pull redis:5.xx # 拉取指定版本

Docker 镜像

Docker 镜像是一个轻量级、独立的、可执行的软件包,包含了应用程序运行所需的所有内容:代码、运行时、库、环境变量、配置文件等。镜像是只读的模板,可以用来创建 Docker 容器。每个镜像可以包含一个完整的操作系统或仅包含运行应用程序所需的最小环境。镜像的分层结构和缓存机制使得镜像的构建和分发更加高效。

Docker 镜像的常用命令有以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 构建镜像
docker build -t myDevApp:1.0 .

# 列出本地镜像
docker images

# 删除镜像
docker rmi <IMAGES-NAME>:<TAG>

# 标记镜像
docker tag myDevApp:1.0 myUatApp:1.0

# 导出镜像
docker save -o myUatApp_v1.0.tar myUatApp:1.0

# 导入镜像
docker load -i myapp_v1.tar

Docker 容器

Docker 容器是由 Docker 镜像创建的运行实例。它包含应用程序及其所有依赖项,并在一个隔离的环境中运行。容器是轻量级的,可以在几秒钟内启动,且与宿主系统资源共享,同时保持进程隔离和文件系统独立。由于容器使用相同的操作系统内核,它们比虚拟机更高效,并且占用更少的资源。

Docker 容器的常用命令有以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 启动/运行一个容器
docker run [options] <IMAGE-NAME>

# 列出正在运行的容器
docker ps

# 列出所有容器,包含已停止的
docker ps -a

# 停止容器
docker rm <IMAGES-NAME>/<CONTAINER-ID>

# 启动已停止的容器
docker start <CONTAINER-NAME>/<CONTAINER-ID>

# 重启容器
docker restart <CONTAINER-NAME>/<CONTAINER-ID>

# 删除容器
docker rmi <CONTAINER-NAME>/<CONTAINER-ID>

# 查看容器日志
docker logs <CONTAINER-NAME>/<CONTAINER-ID>

# 进入容器
docker exec -it <CONTAINER-NAME>/<CONTAINER-ID> /bin/bash

# 复制文件到容器
docker cp <FILE-PATH/FILE> <CONTAINER-NAME>/<CONTAINER-ID>:/<CONTAINER-INNER-PATH>

# 将文件从容器内复制出来
docker cp <CONTAINER-NAME>/<CONTAINER-ID>:/<CONTAINER-INNER-PATH> <FILE-PATH/FILE>

docekr logs 容器命令补充

一般日志信息太多,有很多我们不需要的信息,此刻可以使用 --tail [NUMBER] 来指定最新的 NUMBER 条数据的日志。当然也可以使用 -f 参数来实时追踪日志。如果将2个参数结合在一起,例如:
1
docker logs --tail 20 -f redis

代表实时查看并跟踪最新的 20 条日志记录,在日常使用用属于比较常用且重要的命令。

我们也可以使用 --since--until 来指定限制只查看某个时间之后和之前的日志

docker run 常用参数详解:

-d/–detach:使容器在后台运行,并返回一个容器ID。例如:

1
docker run -d redis

–name: 为容器指定一个名称。

1
docker run --name my-redis redis

-p(小写)/–public:将容器的端口映射到主机的端口,左边为主机端口,右边为容器端口。

1
docker run -p6379:6379 redis

-P(大写) : 自动映射容器内部所有暴露的端口到主机端口。

1
docker run -P redis 
  • -e/–env:设置容器内环境变量。格式为 key=value
    1
    docker run -e "MYSQL_ROOT_PASSWORD=123456" mysql
  • -v/–volume:挂载主机目录或数据卷到容器内。
    1
    docker run -v ./redisLogs:/data redis
  • –rm:容器停止后自动删除容器。一般不用 一般作为临时容器启动时使用。
    1
    docker run --rm redis
  • –network:指定容器使用的网络。
    1
    2
    3
    # 前提需要已经创建有 my-network 这个自定义网络,否则会报错
    # 可以使用 docker network create my-network 命令来创建网络
    docker run --network my-network nginx
  • –restart: 指定容器的重启策略。常用策略包括 no(默认,不重启),on-failure(失败时重启),always(总是重启)。
    1
    docker run --restart always nginx
  • –cpus:限制容器可以使用的cpu量:
    1
    docker run --cpus 2 redis
  • –memory:限制容器使用的内存。
    1
    docker run --memory 512m redis

(篇幅有限,更多命令详查官网)

可选参数较多,以下是一个综合案例,展示了如何使用多个参数启动一个容器:
1
2
3
4
5
6
7
8
9
10
docker create network nginx-network

docker run -d \
--name my-nginx \
-p 80:80 \
-v ./nginx:/data/ \
-e "MY_ENV_VAR=value" \
--network nginx-network \
--restart=always \
nginx

如上这个命令会

  • 后台运行一个名为 my-nginxNginx 容器
  • 将主机的端口 80 映射到容器的端口 80
  • 挂载主机当前目录的 /mydata 到容器内的 /data 目录
  • 设置环境变量 MY_ENV_VARvalue
  • 使用 nginx-network 网络
  • 设置容器总是重启

Docker Compose 工具

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过编写一个 docker-compose.yml 文件,可以描述应用程序的服务、网络和卷。这个文件使用 YAML 语法,便于人类阅读和编辑。

一个典型的 docker-compose.yml 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# vsersion: '3.8' # 指定 Compose 文件的版本,新版本已弃用,向下兼容,所以不必再写

services: # 定义服务
web: # 第一个服务
container_name: mynginx # 容器名称
image: nginx:latest # 使用的镜像
ports: # 端口映射
- "80:80"
volumes: # 数据卷
- ./webdata:/usr/share/nginx/html
networks: # 使用的网络
- myAppNetwork
environment: # 设置环境变量
- NGINX_HOST=localhost
- NGINX_PORT=80
restart: always # 重启策略
app: # 第二个服务
image: myUatApp:1.0
port:
- "8080:8080"
networks:
- myAppNetwork
redis: # 第三个服务
image: redis:latest
ports:
- "6379:6379"
networks:
- myAppNetwork
environment: # 设置环境变量
- REDIS_PASSWORD=mysecretpassword

networks: # 定义网络,无需提前创建,启动时若没有这个网络会自动取创建
myAppNetwork:
docker compose 常用命令:

docker-compose up:启动并运行 docker-compose.yml 文件中定义的所有服务。如果使用 -d 选项,则服务将在后台运行

1
2
docker-compose up
docker-compose up -d

docker-compose stop:停止所有服务或指定的服务,但不会删除容器。

1
2
docker-compose stop # 停止全部
docker-compose stop mynginx # 只停止里面的 mynginx 容器

docker-compose start:启动已停止的所有服务或指定的服务。

1
2
docker-compose start
docker-compose start mynginx

docker-compose restart:重启所有服务或指定的服务。

1
2
docker-compose restart
docker-compose restart mynginx

docker-compose logs:查看服务的输出日志。如果指定服务名称,则只显示该服务的日志。

1
2
docker-compose logs
docker-compose logs myservice

docker-compose down:停止并删除 docker-compose.yml 文件中定义的所有服务、网络和卷(除非使用 -v 选项)。

1
2
docker-compose down
docker-compose down -v

docker-compose ps:列出所有正在运行的容器。

1
docker-compose ps

docker-compose rm:删除已停止的容器。

1
2
docker-compose rm
docker-compose rm -f # -force 表示强制删除,无需确认

(篇幅有限,更多命令详查官网)

结语

通过本篇博客,我们深入探讨了 Docker 及其基本使用方法。Docker 作为一种现代化的容器技术,不仅简化了应用程序的部署和管理,还提升了开发和运维的效率。在本文中,我们从 Docker 的基本概念入手,逐步介绍了容器、镜像、仓库 以及 Docker Compose 等重要组件。我们还阐述了如何使用 Docker Compose 定义和启动多容器应用。

通过示例和常用命令的讲解,相信大家已经对 Docker 的使用有了较为全面的了解。无论是单一容器的简单应用,还是多容器协作的复杂应用,Docker 都能提供强有力的支持和灵活的解决方案。

希望通过本篇博客,能够帮助大家更好地理解和使用 Docker,从而在实际工作中提高效率,简化流程。种一棵树最好的时间是十年前,其次是现在,如果你还没有尝试过 Docker,那么现在正是一个开始的好时机。通过不断实践和探索,相信你会发现 Docker 的强大之处,并在工作中获得更多的便利和提升。

感谢阅读,希望本文对你有所帮助!

  • 标题: Docker 的基本使用
  • 作者: HYF
  • 创建于 : 2024-07-04 23:51:29
  • 更新于 : 2024-07-27 21:21:52
  • 链接: https://youfeng.ink/docker-base-using-fd3e77a2e6a9/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。