Docker基本概念、安装配置、容器化部署及常用命令。
前言
Docker是一种操作系统层面的轻量级虚拟化技术,由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器(Container)。与虚拟机(VM)相比,Docker使用宿主机的操作系统,启动更快。每个容器只运行所需的应用程序和依赖项,资源消耗更少。Docker将操作系统、运行时环境、第三方软件库和依赖包、应用程序、环境变量、配置文件、启动命令等打包在一起,以便在任何环境中都能正常运行。
基本概念
Docker Daemon
Docker使用Client-Server架构,Docker Clinet和Docker Daemon之间通过Socket或Restful API进行通信。
Docker Daemon是服务端的守护进程,负责管理Docker的各种资源,接受并处理来自客户端的请求,然后将结果返回给客户端。
Docker镜像与容器
镜像(Images)是一个只读的容器模板,含有启动Docker容器所需的文件系统结构及内容。容器是Docker的运行实例,它提供了一个独立的可移植的环境。Docker以镜像和在镜像基础上构建的容器为基础,以容器开发、测试、发布的单元将应用相关的所有组件和环境进行封装,避免了应用在不同平台间迁移所带来的依赖问题,确保了应用在生产环境的各阶段达到高度一致的实际效果。
Docker仓库
Docker仓库(Registry)是用来集中存储和管理Docker镜像的地方。常用的有Dockerhub,用户可在此分享和下载Docker镜像,以实现镜像的共享和复用。
安装配置
Docker官网在国内需要vpn才能访问,可通过国内镜像地址下载。Docker的使用可通过命令行方式,也可通过图形化工具Docker Desktop。
Windows系统中启动Docker Desktop的先决条件(以下二选一)
- 安装WSL(推荐)
- 开启Hyper-V功能
容器化与Dockerfile
Dockerfile是Docker用来构建镜像的指令文件,Docker容器化包含以下三个部分
创建一个Dockerfile
使用Dockerfile构建镜像
使用镜像创建和构建容器
例如要使用node在alpine中运行一个index.js文件,对应的Dockerfile为
1 | FROM node:14-alpine |
.dockerignore是Docker镜像构建的ignore文件,通过合理配置可以减少Docker构建上下文大小,加快镜像构建速度,避免将敏感信息(如开发环境配置)打包进镜像,保持生产镜像的简洁性。
Docker Compose
Docker Compose是一个用来定义和运行复杂应用的Docker工具。一个使用Docker容器的应用,通常由多个容器组成。使用Docker Compose不再需要使用shell脚本来启动容器。
Docker Compose通过一个配置文件来管理多个Docker容器。在配置文件中,所有的容器通过services来定义,然后使用docker-compose脚本来启动,停止和重启应用、应用中的服务以及所有依赖服务的容器,非常适合组合使用多个容器进行开发的场景。
最新的Docker已经集成了docker-compose功能,可使用docker compose version命令查看当前版本。
简单示例
下面是一个Docker Compose的简单示例。
配置文件目录结构
1 | ├─ etc |
配置文件docker-compose.yml
Docker Compose配置文件是一个定义服务,网络和卷的YAML文件,默认文件名为docker-compose.yml。与Docker运行一样,默认情况下,Dockerfile中指定的选项(例如,CMD,EXPOSE,VOLUME,ENV)都被遵守,你不需要在docker-compose.yml中再次指定它们。
例如定义一个包含redis和mysql数据的容器,可使用以下配置文件。
1 | # server.yml |
可使用以下命令构建并运行容器(使用-f使用自定义的配置文件,使用-d以后台方式运行)
docker-compose -f server.yml up -d
关闭或移除容器、镜像等
docker-compose -f server.yml down
完整示例
将一个.NET+Vue+MySQL应用打包为Docker镜像的完整方案如下,
1 | my-app/ |
配置数据库Dockerfile
数据库Dockerfile文件如下,
1 | FROM mysql:8.0.1 |
其中init.sql数据库初始化脚本文件如下,
1 | -- init.sql |
my.conf数据库配置文件如下,
1 | [mysqld] |
注:如果MySQL容器初始化脚本未执行,可使用命令cmd.exe /c "docker exec -i mysql_db mysql -uroot -p[MYSQL_ROOT_PASSWORD] < ./mysql/sqlScript/init.sql"手动执行。
配置后端Dockerfile
.NET后端Dockerfile文件如下,
1 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base |
注:执行dotnet restore需要联网环境,若要断网离线构建,应先本地构建bin/Release/net5.0/publish,然后从宿主机复制到容器,对应的Dockfile可简化为:
1 | FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base |
配置前端Dockerfile
Vue前端Dockerfile文件如下,
1 | # 构建阶段 |
注:执行npm install需要联网环境,若要断网离线构建,应先本地构建dist,然后从宿主机复制到容器,对应的Dockfile可简化为:
1 | FROM nginx:1.27.0 |
其中nginx.conf的配置内容如下,
1 | events { |
注:Dockerfile中配置的后端地址http://localhost:8081/为代理地址(由于浏览器同源策略,必须与宿主机的前端访问地址一致),由于宿主机的8081端口指向容器的80端口,因此容器内实际的前端地址仍然为http://localhost:80/。 在location中通过设置proxy_pass相对路径http://backend:80(Docker内置的DNS解析器会自动将backend解析为对应容器的IP地址),将后端请求由http://localhost:80/api/xxx转发到http://backend:80/api/xxx,从而解决跨域问题。
配置Docker Compose
docker-compose.yml配置文件如下,
1 | version: '3.8' |
注:若要断网离线构建backend和frontend,除了修改Dockfile直接使用COPY命令,也可以修改Docker Compose使用volumes挂载文件,具体配置如下:
1 | ... |
配置环境变量
.env配置文件如下,
1 | MYSQL_ROOT_PASSWORD=root1234 |
使用命令docker-compose build以构建上述所有镜像,使用命令docker-compose up -d启动镜像。
导入导出
管道方式打包导出所有镜像(使用此命令导出的镜像,在加载后为<none>:<none>未标签状态,需要手动打标签)docker save -o all-images.tar $(docker-compose images -q)
列表方式打包导出所有镜像(列表项格式为<image-name>:<image-tag>)docker save -o all-images.tar mysql:8.0.1 my-app-backend:latest my-app-frontend:latest
也可以将所有镜像罗列到image-list.txt当中,然后通过文件读取的方式导出docker save -o all-images.tar $(cat image-list.txt)
注:使用列表导出时,请检查所有Dockfile中依赖的基础镜像,例如node:18-alpine等,将他们全部添加进列表中,否则后续docker-compose构建容器时会尝试联网拉取远程基础镜像。
导出配置docker-compose config > docker-compose-export.yml
加载镜像docker load -i all-images.tar
根据导出配置启动服务docker-compose -f docker-compose-export.yml up -d
常用命令
镜像管理
拉取镜像
docker pull [image-url]
使用镜像源拉取(如轩辕镜像中mirror-url为docker.xuanyuan.me, path为library)
docker pull [mirror-url]/[path]/[image-name]:[image-version]
从本地归档文件(.tar)加载镜像到本地镜像库
docker load -i [image-name].tar
通过Shell重定向使用标准输入(stdin)加载镜像(适用于脚本或管道操作)
docker load < [image-name].tar
构建镜像
docker build -t [image-name] .
根据镜像ID重命名镜像名称
docker tag [image-id] [image-name]
运行镜像(使用-d以守护进程/后台方式运行)
docker run [image-name] .
查看所有镜像
docker image ls
docker images
上传镜像
docker push [image-url]
删除镜像
docker rmi [image-name] /
docker image rm [image-name]
从容器创建镜像
docker commit [container-name] [image-name]
保存为镜像文件
docker save -o [image-name].tar [image-name]
容器管理
创建容器
docker create [image-name]
启动运行并命名容器
docker run --name [container-name] [image-name]
例如运行一个基于Ubuntu的容器,可使用以下命令
docker run --name ubuntu_demo -itd docker.xuanyuan.me/library/ubuntu
(注:-itd为组合参数,-i使容器保持交互状态,-t为容器分配一个伪终端,-d在后台运行容器)
若要添加端口映射、卷挂载、环境变量,可在上述命令基础上添加-p、-v、-e参数
docker run -itd --name ubuntu_demo -p 8080:80 -v [host-path]:/home/ubuntu -e [environment-variable]="[your-environment-variable]" docker.xuanyuan.me/library/ubuntu
查看指定容器的挂载详情
docker inspect --format='{{json .Mounts}}' [container-name] | python -m json.tool
进入Ubuntu容器内部
docker exec -it ubuntu_demo bash
在容器内设置临时环境变量(仅对当前会话有效)
export [environment-variable]="[your-environment-variable]"
停止容器
docker stop [container-name]
删除容器
docker rm [container-name] /
docker container rm [container-name]
退出容器
exit
WSL配置Docker
通过WSL使用Docker时可能会缺失一些配置文件。
daemon.json
daemon.json是Docker引擎的配置管理文件,可以统一设置容器的网络、存储、安全、日志等选项。
docker安装后默认没有daemon.json这个配置文件,需要进行手动创建。在linux系统中,配置文件的默认径为:/etc/docker/daemon.json。
可使用以下命令手动创建daemon.json
sudo mkdir -p /etc/docker
sudo touch /etc/docker/daemon.json
sudo nano /etc/docker/daemon.json
例如配置docker镜像,可添加以下配置
1 | { |
保存并退出后可使用以下命令重新加载系统配置,并重启docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker
可使用docker info查看镜像配置是否生效,若仍未生效,可前往Docker Desktop手动设置。
右键点击任务栏Docker图标 → Settings → Docker Engine,修改JSON配置后点击Apply & Restart等待重启完成即可。
docker.service
docker.service文件是用于配置和管理Docker守护进程的systemd单元文件。它定义了Docker服务的启动、停止和重启行为,以及一些关键的配置参数。
如果缺失这个文件,在重启docker时会报错
Failed to start docker.service: Unit docker.service not found
可使用以下命令手动创建docker.service
sudo nano /etc/systemd/system/docker.service
可添加以下配置
1 | [Unit] |
保存后使用以下命令重新加载systemd配置并启动服务
sudo systemctl daemon-reload
sudo systemctl start docker