docker是方便项目环境部署的虚拟化技术,每个docker容器有自己的文件系统和网络接口。本文将参考官网文档,主要介绍docker的基本概念、通过Dockerfile构建镜像,镜像共享、volume mount、docker network、docker-compose、layer caching,方便快速入门docker。
1.docker基本概念
- image镜像,拥有独立的环境,包括文件系统和网络接口。
- container容器,是image的实例,每个运行的容器进程可提供指定服务。
- tag标签,image的标签,标识不同的镜像版本。
- repository仓库,类似git的仓库,repository是docker hub下的仓库,image在仓库中,可从仓库pull镜像,push镜像到仓库。
- volume卷,用于持久化DB、容器路径挂载宿主机,保证容器环境可动态加载。
- layer层,根据Dockerfile构建镜像时将根据每层指令进行操作,关于依赖下载的layer可以通过缓存cache,避免每次修改文件重复执行install dependency操作。
- network网络,container相互隔离,每个container都有独立的网络接口,不同container可根据同一个network进行网络通信。
2.基于Dockerfile构建镜像
创建镜像容器的第一种方式是:docker run image,如果本地image不存在,则会自动从docker hub上拉取镜像。第二种方式就是通过Dockerfile文件构建镜像。
Dockerfile示例
# syntax=docker/dockerfile:1
FROM node:12-alpine
WORKDIR /app
RUN yarn install --production
COPY . .
CMD ["node", "src/index.js"]
ENTRYPOINT ["ls","-l"]
Dockerfile是关于指令的文件,可查阅官方文档了解每个指令的作用。
上述指令分别为:
FROM:当前要构建的镜像的,来源image,相当于父镜像。
WORKDIE: 工作目录。
RUN:镜像执行的语句。
COPY:拷贝宿主机的文件至镜像。
CMD:给正在运行的容器提供初始值命令, run image(运行镜像)时容器的初始命令值,若在run中手动增加命令值,则会替换CMD的初始值。
ENTRYPOINT: 同CMD,为运行容器的初始命令值,区别在run中手动增加会追加到ENTRYPOINT后面。
-
构建镜像:
docker build -t imageName .
末尾的.
表示Dockerfile所在的地址,即当前目录。 -
查看镜像:
docker images -
运行镜像容器:
docker run --name containerName -p 3000:3000 imageName
其中, -p表示可选参数中的端口映射,前面是host端口,后面是容器端口。
--name是给容器设置别名,下次可使用该容器实例:
docker start containerName
其他可选参数可通过:docker run --help查看。 -
查看容器列表:
docker ps -
关闭容器:
docker stop containerId/containerName
3.镜像共享repository
类似Github,不同主机可以通过pull/push镜像至Docker Hub的repository来共享image。
-
拉取镜像
docker pull repository/image:tag -
本地镜像打标签
docker tag sourceImage:tag targetImage:tag -
推送镜像
docker push repository/image:tag
4.named volume与volume mount
volume是实现容器和宿主机数据同步的一种方式,有两种类型:named value和volume mount
-
named volume
命名卷,可用于持久化DB数据,由于容器彼此隔离,容器中的数据无法共享,通过指定named volume,可将container中的数据持久化至宿主机中。
创建volume:
docker volume create volumeName
开启容器时指定volume:
docker run -p 3000:3000 -v volumeName:containerPath image:tag
容器内数据存储地址为containerPath,该指令可使数据同步到volumeName中。
查看volume详情
docker volume inspect volumeName
[
{
"CreatedAt": "2022-02-26T07:50:45Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todolist/_data",
"Name": "todolist",
"Options": {},
"Scope": "local"
}
]
其中,Mountpoint挂载点即宿主机存储volume数据的位置。
-
volume mount
如果只是简单地持久化DB数据,可以使用named volume;但如果要同步代码,保证宿主机的改动可以同步到容器中,比如实现热部署。这时就需要指定容器应用在宿主机的Mountoint挂载点(named volume是docker自动指定的挂载点)。
指定挂载点运行容器:
docker run -p 3000:3000 -w /app-v "$(pwd):/app"
imageName
在-v中,$(pwd)表示当前目录,该指令表示当前container的/app路径挂载到当前目录,这样当前目录改动代码后容器内代码也随着改动。
5.docker network
由于docker容器彼此独立,容器间无法直接通信。但不同容器需要通信完成服务,比如Nginx-Php应用容器需要与Mysql容器通信,因此需要通过docker network进行容器通信,同一网络下的容器可进行通信,不同网络下的容器无法通信。
创建network
docker network create networkName-
多容器通信
开启mysql容器,指定network:
docker run -d
--network todo-app --network-alias mysql
-v todo-mysql-data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=secret
-e MYSQL_DATABASE=todos
mysql:5.7开启application容器,指定network:
docker run -dp 3000:3000
-w /app -v "$(pwd):/app"
--network todo-app
-e MYSQL_HOST=mysql
-e MYSQL_USER=root
-e MYSQL_PASSWORD=secret
-e MYSQL_DB=todos
node:12-alpine
sh -c "yarn install && yarn run dev"上述开启了两个container,并指向了同一个network;mysql容器通过-e设置环境变量,将参数传递到mysql容器中,登录mysql并创建database;app容器也设置了环境变量传递到app容器中用于连接登录mysql容器。
-
查看network信息
官方推荐了一个镜像nicolaka/netshoot,可用排查和调试网络问题。运行该镜像并设置该镜像的network为需要调试的网络。可选项-it表示运行并进入容器,使用DNS工具dig命令即可查询host的ip地址,如dig mysql(上述mysql容器中,--network-alias mysql设置了容器的网络别称)。
6.docker-compose运行容器服务
是不是觉得一个个开启容器的方式优点麻烦,docker-compose工具就是用来解决该问题,可以理解它是管理容器运行的工具。该工具可以根据yml配置文件,一行简单的命令即可开启多个相关容器,实现应用服务部署(比如LNMP服务搭建)。
安装docker-compose很简单就不介绍了。
-
创建docker-compose.yml
示例:
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
进入docker-compose.yml所在目录。
运行应用服务:
docker-compose up
配置文件解析:创建volume用于持久化Mysql数据,并开启app容器和Mysql容器。
关于network:
需要注意的是,compose文件中并没有指定network,但docker-compose会自动创建network,并给每个容器分配。
可以打开localhost:3000运行下该项目(测试的是官网todolist示例应用),如下图所示。
7.layer caching镜像层缓存依赖
关于第二点Dockerfile构建镜像的补充优化,其中有一层指令是下载依赖,意味着每一次build镜像时都会去下载依赖,即使只是修改了一行无关依赖的业务代码,显然这很低效不合理。
- 优化方式即layer caching,对指定层依赖文件进行缓存;
- 实现方式:利用copy指令复制依赖文件实现layer caching。
- 示例:COPY package.json yarn.lock ./
同时需要注意增加.dockerignore文件,根据具体情况指定忽略的copy文件
以上是docker的基础知识以及基本使用方法,想要深入了解更多特性可以参考官网文档。