做开发和运维的人,几乎都遇到过这样的问题:应用在开发环境能跑,部署到测试环境就出问题;测试环境没问题,到了生产环境又报错。每次部署都要重新配置环境,安装依赖,费时费力还容易出错。
传统的解决方案是用虚拟机(VM),把应用和环境一起打包成虚拟机镜像。但虚拟机有个问题——太重了。每个虚拟机都包含一个完整的操作系统,启动慢(几分钟),占用资源多(几个GB),一台物理机跑不了几个虚拟机。
Docker就是为了解决这个问题而生的。Docker是一个开源的容器化平台,它用容器(Container)来打包和运行应用。容器和虚拟机类似,也是一种隔离环境,但容器更轻量——它不包含完整的操作系统,只包含应用运行所需的库和依赖,共享宿主机的内核。所以容器启动快(几秒),占用资源少(几十MB),一台物理机可以跑几十个甚至上百个容器。
Docker的核心思想是"构建一次,到处运行"(Build once, run anywhere)。你用Dockerfile定义应用的运行环境,构建成镜像(Image),然后这个镜像可以在任何安装了Docker的机器上运行,不管是开发机、测试机还是生产服务器,环境完全一致。这就彻底解决了环境不一致的问题。
Docker的基本概念
Docker有三个核心概念:镜像(Image)、容器(Container)、仓库(Repository)。
镜像(Image)是一个只读的模板,包含了应用运行所需的操作系统、软件、代码、配置等。比如一个Ubuntu镜像,包含了Ubuntu操作系统的基础文件;一个Nginx镜像,包含了Ubuntu基础+Nginx软件+默认配置。镜像类似于虚拟机的快照,但更轻量。镜像是分层的,每一层都是只读的,构建镜像时一层层叠加,这样可以复用底层,节省存储空间。
容器(Container)是镜像的运行实例。你可以从一个镜像启动多个容器,每个容器都是独立的运行环境,有自己的文件系统、网络、进程空间。容器类似于虚拟机的运行实例,但更轻量、启动更快。容器是可读写的,运行时产生的数据保存在容器的可写层中,但容器删除后数据也会丢失(除非用数据卷Volume持久化)。
仓库(Repository)是存放镜像的地方。Docker Hub是官方的公共仓库,里面有几十万个公开镜像,包括Ubuntu、Nginx、MySQL、Redis、WordPress等,你可以直接拉取使用。你也可以把自己构建的镜像推送到Docker Hub或私有仓库,方便分发和部署。
安装和使用Docker
Docker支持Linux、Mac、Windows三大平台。在Linux上安装最简单,因为Docker原生就是为Linux设计的。以Ubuntu为例:
# 安装Docker
curl -fsSL https://get.docker.com | sh
# 启动Docker服务
sudo service docker start
# 测试安装
sudo docker run hello-world运行docker run hello-world后,Docker会从Docker Hub拉取hello-world镜像,然后启动一个容器运行它。如果看到"Hello from Docker!"的输出,说明安装成功。
Docker的常用命令:
# 拉取镜像
docker pull nginx
# 查看本地镜像
docker images
# 启动容器(-d后台运行,-p端口映射,--name指定名称)
docker run -d -p 80:80 --name mynginx nginx
# 查看运行中的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a
# 停止容器
docker stop mynginx
# 启动已停止的容器
docker start mynginx
# 进入容器
docker exec -it mynginx /bin/bash
# 删除容器
docker rm mynginx
# 删除镜像
docker rmi nginx
# 查看容器日志
docker logs mynginxDockerfile构建镜像
除了使用公开镜像,你还可以用Dockerfile自定义构建镜像。Dockerfile是一个文本文件,包含一系列指令,用来描述如何构建镜像。
一个简单的PHP应用Dockerfile示例:
# 基础镜像
FROM php:7.0-apache
# 作者信息
MAINTAINER yourname <your@email.com>
# 安装扩展
RUN docker-php-ext-install mysqli pdo pdo_mysql
# 复制代码到容器
COPY . /var/www/html/
# 设置工作目录
WORKDIR /var/www/html
# 暴露端口
EXPOSE 80
# 启动命令
CMD ["apache2-foreground"]然后在Dockerfile所在目录运行构建命令:
docker build -t myphpapp .-t指定镜像名称和标签,.表示使用当前目录的Dockerfile。构建完成后,就可以用docker run启动这个镜像了。
Docker Compose
如果你的应用由多个服务组成(比如Web+MySQL+Redis),手动一个个启动容器、配置网络会很麻烦。Docker Compose是一个用于定义和运行多容器Docker应用的工具,你用一个docker-compose.yml文件定义所有服务,然后一条命令就能启动所有服务。
一个简单的docker-compose.yml示例:
version: '2'
services:
web:
build: .
ports:
- "80:80"
depends_on:
- mysql
- redis
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: myapp
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:3.0
volumes:
mysql_data:然后运行:
docker-compose up -d这会自动构建web镜像、拉取mysql和redis镜像、创建数据卷、配置网络、启动所有服务。一条命令搞定整个应用的部署。
Docker的优势
第一,环境一致性。Docker镜像包含了应用运行所需的一切,在任何环境运行都是一样的,彻底解决了"在我机器上能跑"的问题。
第二,快速部署。容器启动只需要几秒,比虚拟机快得多。部署应用时,只需要拉取镜像、启动容器,几分钟就能完成部署。
第三,资源高效。容器共享宿主机内核,不需要完整的操作系统,资源占用少。一台服务器可以跑几十个容器,资源利用率高。
第四,易于扩展。容器轻量、启动快,可以快速创建和销毁。在流量高峰时,可以快速启动更多容器应对流量;流量低时,销毁多余容器节省资源。这就是微服务和弹性伸缩的基础。
第五,版本管理和回滚。Docker镜像有版本标签,可以管理不同版本的应用。如果新版本有问题,可以快速回滚到旧版本的镜像。
注意事项
第一,数据持久化。容器的可写层是临时的,容器删除后数据也会丢失。需要持久化的数据(如数据库数据、用户上传文件)应该用数据卷(Volume)挂载到宿主机,或者用数据容器。
第二,安全。容器共享宿主机内核,隔离性不如虚拟机。如果容器被攻破,可能影响宿主机和其他容器。生产环境使用时要注意安全配置,比如不要用root用户运行容器、限制容器的资源使用、不要在容器里运行不必要的服务。
第三,日志管理。容器里的应用日志默认输出到stdout/stderr,可以用docker logs查看。但如果日志量大,建议用日志驱动(如fluentd、syslog)集中收集和管理日志。
第四,网络配置。Docker默认用bridge网络,容器之间可以通过IP通信,但IP是动态分配的,不固定。建议用自定义网络或Docker Compose的服务名来通信,服务名会自动解析为容器IP。
总结
Docker是近年来最具革命性的技术之一,它改变了应用的部署和运维方式。用容器化的方式打包应用,实现了"构建一次,到处运行",解决了环境不一致的问题,提升了部署效率,降低了资源消耗。
如果你还在手动配置环境、为部署问题头疼,建议学习和使用Docker。它会让你的开发和运维工作轻松很多。Docker的学习曲线不陡,基本概念和命令一两天就能掌握,但带来的效率提升是巨大的。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录