写在前面:
本篇简单介绍一下如何入手 Docker,从 创建/拉取 镜像,再到运行和管理容器,还包括导出容器等操作。这里先贴一下官方的文档地址:
一、Docker 介绍
作为一个开源的应用容器引擎,Docker 可以让开发者将应用以及应用的依赖打包到一个可移植的容器中,然后发布到任何安装了 Docker 的服务器上运行。这些容器就像一个个轻量级的虚拟机,但与传统虚拟机相比,Docker 容器更加高效、快速和资源友好。
主要特点:
-
轻量级
Docker 容器共享主机内核,不需要像虚拟机那样模拟完整的操作系统,因此启动速度极快,通常在几秒钟内就能启动。
占用的资源少,多个容器可以在同一台服务器上高效运行,提高了服务器的利用率。 -
可移植性
由于容器包含了应用及其所有依赖,所以可以在不同的环境中轻松迁移,无论是从开发环境到测试环境,还是从本地服务器到云服务器。
保证了应用在不同环境中的一致性运行,减少了因环境差异导致的问题。 -
高效性
容器的快速启动和停止特性使得应用的部署和扩展变得非常容易。
可以根据需求快速创建和销毁容器,实现弹性的资源分配。 -
隔离性
每个容器都有自己独立的文件系统、网络和进程空间,实现了应用之间的隔离。
一个容器中的问题不会影响到其他容器,提高了系统的稳定性和安全性。
核心组成:
-
镜像(Image)
是一个只读的模板,包含了应用程序及其所有依赖(如库、框架、配置文件等)。
可以从 Docker 仓库中下载或自己创建镜像,然后基于镜像创建容器。 -
容器(Container)
是由镜像创建的运行实例,是一个独立的运行环境。
可以对容器进行启动、停止、删除等操作,也可以在容器中运行应用程序。 -
仓库(Repository)
用于存储和分发 Docker 镜像,可以是公共仓库(如 Docker Hub),也可以是私有仓库。
开发者可以将自己创建的镜像推送到仓库中,以便在不同的环境中使用。
使用场景:
-
应用部署
简化了应用的部署过程,提高了部署的效率和可靠性。
可以快速将应用部署到多台服务器上,实现大规模的应用部署。 -
微服务架构
适合用于构建微服务架构,每个微服务可以运行在一个独立的容器中。
-
开发环境一致性
保证了开发、测试和生产环境的一致性,减少了因环境差异导致的问题。
开发者可以在本地使用与生产环境相同的容器来进行开发和测试。
二、创建镜像
这里介绍几种常见的创建镜像的方式,大家可以根据自己需求选择。
2.1 从 Docker Hub 拉取镜像
第一步:登录/注册 Docker Hub
如果没有则先去官网(https://hub.docker.com/)注册一个,然后登录即可(Desktop版图形化操作即可,普通的则打开终端输入 " docker login ")。
第二步:查找所需的镜像
可以直接在官网去搜索即可,这里写几个常用的镜像:
- Alpine :基于轻量级 Linux 操作系统的镜像,体积非常小巧,只有 5MB 左右,提供了一些基本的工具和包,如
bash
、curl
、gcc
等,适合构建轻量级的容器。 - Ubuntu:基于 Debian 的 Linux 操作系统,常用版本(LTS):22.04、20.04、18.04;
- Nginx:广泛使用的 Web 服务器软件,也可用作反向代理、负载均衡和 HTTP 缓存服务器。结合其他技术如 WordPress 等,可以用于构建高性能的 Web 应用程序。
- Redis:基于内存的数据存储系统,常用于实时数据缓存、排名、计数器、分布式会话管理等方面,具有快速、可靠且易于使用的特点,适合构建可扩展的分布式系统。
- MySQL:流行的关系数据库管理系统,支持多数据类型、多连接和高性能,是开发人员构建数据库应用程序的常用选择之一。
- Node.js:基于 JavaScript 的后端服务器技术,支持高性能、非阻塞 I/O 和事件驱动编程,许多开发者使用它来构建 Node.js 的 Web 应用程序和 Web 服务。
- Tomcat:一个流行的 Java Web 应用服务器,用于运行 Java Web 应用程序3。
- CentOS:一种常用的 Linux 发行版镜像,提供了稳定的操作系统环境,适合用于各种服务器应用的部署。
第三步:拉取所需镜像
在命令行中输入docker pull [镜像名称]:[标签]
。
如果不指定标签,默认会拉取 latest
(最新)标签的镜像。
例如,要拉取官方的 Ubuntu 镜像,可输入
bash
docker pull ubuntu # 最新版
docker pull ubuntu:22.04 # 特定版
后续:可创建自己的镜像仓库
登录上 Docker Hub,在存储库页面上,选择创建存储库。
将其进行命名,比如<you-username>/my-Privateal-repo,将可见性设置为私有。
配置完自己镜像后,可以上传到仓库。上传镜像之前,先对镜像进行标记:
bash
docker tag my_image:latest <you-username>/my-Privateal-repo
使用 docker push
命令将标记后的镜像上传到私有仓:
bash
docker push <you-username>/my-private-repo
当然,可以在另外机器上或使用 pull 拉取验证镜像。
2.2 用 Dockerfile 创建镜像
Dockerfile 是一个文本文件,包含了一系列指令,用于描述如何构建一个 Docker 镜像。这些指令会按照顺序依次执行,最终生成一个包含特定应用及其依赖的镜像,使用 Dockerfile 创建镜像是一种常见且高效的方式,
常见指令:
FROM
:指定基础镜像,它是构建新镜像的起点。例如:FROM ubuntu:22.04
。RUN
:在镜像构建过程中执行命令。可以用于安装软件包、配置环境等。例如:RUN apt-get update && apt-get install -y python3
。COPY
或ADD
:将本地文件或目录复制到镜像中。例如:COPY. /app
将当前目录下的所有文件复制到镜像中的/app
目录。WORKDIR
:设置工作目录。例如:WORKDIR /app
将后续命令的工作目录设置为/app
。CMD
或ENTRYPOINT
:指定容器启动时要执行的命令。例如:CMD ["python", "app.py"]
表示启动容器时运行python app.py
命令。
示例:
先编写一个 app.py 文件:
python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, Docker!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
再创建一个 Dockerfile 文件:
bash
FROM python:3.10
WORKDIR /app
COPY..
RUN pip install flask
EXPOSE 5000
CMD ["python", "app.py"]
上面的 Dockerfile 中,设置了工作目录,拷贝当前目录文件到镜像内,并安装了 Flask 库,暴露容器的 5000 端口,最后在容器启动后运行命令启动程序。
接下来只需要在包含 Dockerfile 和 app.py 文件的目录下,运行构建镜像即可:
bash
docker build -t myflaskapp:latest .
其中 -t
参数指定镜像的名称和标签,最后的 .
表示 Dockerfile 所在的目录。
构建镜像后,启动容器即可:
bash
docker run -p 5000:5000 myflaskapp:latest
这里将容器的 5000 端口映射到主机的 5000 端口,这样就可以在浏览器中访问http://localhost:5000
来查看 Flask 应用的输出。
Dockerfile 的优势:
- Dockerfile 本身就是一种文档,它清晰地展示了镜像的构建过程和包含的内容。其他开发人员可以更容易理解和使用这个镜像;
- 可以根据具体需求自定义镜像的内容和配置。可以选择不同的基础镜像、安装特定的软件包、设置环境变量等,满足各种复杂的应用场景;
- 可以确保每次构建的镜像都是一致的,无论在哪个环境中构建。
存在的不足:
- 当构建复杂的镜像时,Dockerfile 可能会变得冗长和复杂,需要合理组织指令和管理依赖关系;
- 如果配置中使用了不可信的源或安装了未知的软件包,可能会引入安全风险。需要谨慎选择基础镜像和软件源;
- 当基础镜像较大或者需要下载大量的软件包时,构建过程可能会比较耗时,并且依赖于良好的网络连接。
之前我们遇到过,当配置的软件源更新或者网络原因等,导致无法构建甚至版本控制不理想等问题。所以对于相对复杂的镜像环境,还是不建议这样构建,直接传输镜像会更稳定。
2.3 导出的镜像文件直接导入
Docker 支持直接把容器导出成 tar 的压缩文件,然后从这个文件导入镜像,即可完美复刻容器的环境和内容。
1. 找出要导出容器的 名称 或 ID
bash
docker ps # 会列出正在运行的容器
docker ps -a # 会列出所有的容器
2. 导出容器到 .tar 文件
bash
docker export container_name > container.tar
后面的文件名可以自己指定
3. 在目标电脑上导入镜像
bash
docker import container.tar new_image_name:tag
其中 new_image_name
是新镜像的名称,tag
是标签(可选)。
这种方法的好处就是:对于特定状态的容器,可以快速地在不同环境中进行迁移,无需重新构建镜像。如果目标环境没有网络连接或者网络受限,这种方式可以避免从远程仓库拉取镜像的问题。
当然,与使用 Dockerfile 构建的镜像不同,通过这种方式导入的镜像没有构建历史记录。这可能会在一些需要追踪构建过程或进行调试的情况下带来不便。
三、运行和管理容器
3.1 命令行运行
可以基于之前生成的镜像来启动容器,当然一个镜像可以启动多个容器,但是一个容器一定是基于某个镜像的。命令比较简单,这里就着重给大家介绍几个常用的配置。
1. 分离模式
以分离模式(detached mode)运行容器,即容器在后台运行,不会将容器的输出打印到终端。
bash
docker run -d my_image
2. 映射端口
将主机的 某个 端口映射到容器的 指定 端口,比如 8080-80,这样可以通过访问主机的 8080 端口来访问容器内运行在 80 端口的服务。
bash
docker run -p 8080:80 my_image
3. 容器命名
为容器命名,方便后续对该容器进行管理和识别。不写则会随机生成,可用 docker ps -a 查找。
bash
docker run --name my_container my_image
4. 挂载目录
将主机上的指定目录挂载到容器内的指定目录,实现数据持久化,并且两侧是同步的。
bash
docker run --name my_container -v /host/data:/container/data my_image
5. 设置环境变量
设置环境变量和值,容器内的应用可以读取这个环境变量。
bash
docker run --name my_container -e MY_ENV_VARIABLE=value my_image
6. 限制内存
限制容器使用的内存,防止容器过度占用主机资源。(Windows 下可能不行,得改 WSL2配置)
bash
docker run --name my_container --memory 512m my_image
7. 限制核心
限制容器最多使用主机 CPU 核心数。(Windows 下可能不行,得改 WSL2配置)
bash
docker run --name my_container --cpus 0.5 my_image
8. 连接网络
将容器连接到 Docker 网络,如果该网络不存在,Docker 会自动创建。这样可以方便容器之间的通信和网络隔离。(当然,网络模式有很多种,我的另一篇有详细介绍)
bash
docker run --name my_container --network my_network my_image
9. 退出重启
设置容器的自动重启策略为总是在退出时自动重启。这在容器因某些原因意外退出时很有用,可以确保服务的连续性。
bash
docker run --name my_container --restart always my_image
容器开启后,就可以运行程序了,当然可以打开新的终端,输入命令进入到容器内部:
bash
docker exec -it [容器名称或 ID] /bin/bash
这里的 -i
表示允许交互,-t
表示分配一个伪终端。这样就可以进入容器并启动一个 bash shell。
想退出用 exit 即可,但是退出后容器默认会在后台运行。
停止容器:
bash
docker stop [容器名称或 ID]
发送一个 SIGTERM 信号给容器,让容器内的主进程有机会进行优雅的关闭。如果容器在一段时间内(默认是 10 秒)没有停止,Docker 会发送一个 SIGKILL 信号强制停止容器。
删除容器:
bash
docker rm [容器名称或 ID]
删除一个已停止的容器。如果容器正在运行,需要先停止容器才能删除。
bash
docker rm -f [容器名称或 ID]
强制删除一个正在运行的容器。使用这个命令时要注意,可能会导致数据丢失或其他问题。
查看容器日志:
bash
docker logs [容器名称或 ID]
查看容器的日志输出。可以使用-f
参数来实时跟踪日志输出。
重启容器:
bash
docker restart [容器名称或 ID]
复制文件:
bash
docker cp [源路径] [容器名称或 ID]:[目标路径]
将本地文件或目录复制到容器中。
bash
docker cp [容器名称或 ID]:[源路径] [目标路径]
将容器中的文件或目录复制到本地。
3.2 Docker Compose
Docker Compose 是一个用于定义和运行多容器应用程序的工具,它是开启精简高效的开发和部署体验的关键。可以一次性启动或停止多个相关容器,提高开发和调试效率。
可以在单个易于理解的 YAML 配置文件中轻松管理服务、网络和卷。然后,通过一个命令,就可以从配置文件中创建并启动所有服务。
注意,适用于多容器和复杂管理的情况,容器较少的情况下就没有必要了。
使用之前需要安装,这里不具体介绍,根据官方文档即可。可以用此命令查看:
使用需要创建一个 docker-compose.yml 文件,在文件中定义服务(容器)、网络、卷等。
这里展示一个示例,包含一个 Web 服务器(Nginx)和一个后端应用(假设是一个 Python Flask 应用):
bash
services:
web:
image: nginx
ports:
- "8080:80"
volumes:
-./nginx_config:/etc/nginx/conf.d
networks:
- mynetwork
app:
build:.
command: python app.py
volumes:
- app_data:/app/data
networks:
- mynetwork
environment:
- DB_HOST=db
- DB_PORT=5432
- DB_NAME=mydb
- DB_USER=myuser
- DB_PASSWORD=mypassword
db:
image: postgres
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=myuser
- POSTGRES_PASSWORD=mypassword
- POSTGRES_DB=mydb
networks:
- mynetwork
volumes:
app_data:
db_data:
networks:
mynetwork:
driver: bridge
上面配置中,通过 networks
部分定义了一个名为 mynetwork
的网络,类型为 bridge
。三个服务(web
、app
和 db
)都连接到这个自定义网络,使得它们可以通过服务名称相互通信。
定义了两个卷 app_data
和 db_data
。web
服务将本地的 ./nginx_config
目录挂载到容器内的 /etc/nginx/conf.d
,用于配置 Nginx。
app
服务将卷 app_data
挂载到容器内的 /app/data
,用于数据存储。db
服务将卷 db_data
挂载到容器内的 /var/lib/postgresql/data
,用于 PostgreSQL 数据库的数据存储。
四、总结
上面详细介绍了 Docker 的基本操作,涵盖了生成镜像、运行容器以及管理容器等多方面内容。然而,Docker 作为一款功能极为强大的软件,其能力远不止于此。
在容器间的交互方面,Docker 支持容器间的加密通讯,确保数据在不同容器之间传输的安全性和保密性。通过加密机制,敏感信息得以在复杂的容器化环境中安全流转。
同时,Docker 拥有丰富的插件功能。例如,某些插件可以实现更高效的存储管理,优化容器对存储资源的利用;还有些插件能够增强网络配置的灵活性,为容器间的通讯提供更多定制化的选项。此外,插件还可以与其他工具和技术进行集成,进一步提升 Docker 在不同场景下的适用性和实用性。
官方文档内容也比较多,大家按需学习即可。