Docker简介
软件开发比较麻烦的就是环境配置。换一台机器就得重来一次,操作不难就是耗时耗力,很多人就想,能不能从根本上解决问题,让我们的应用程序自己带着环境和应用依赖,也就是说,部署的时候,把原始环境一模一样地复制过来。
Docker是一个是一个开源的应用容器引擎,是软件部署的解决方案,可以让开发者可以打包他们的应用以及依赖包到一个轻量级的、可移植的、自给自足的镜像中。然后发布到任何流行的 Linux
服务平台。
Linux
文件管理子系统由bootfs
和rootfs
两部分组成bootfs
包含了bootloader
(引导加载程序) 和kernal
(内核)rootfs
root
文件系统,包含的就是典型的Linux
系统中的标准目录和文件- 不同的
Linux
发行版,bootfs
基本一样,而rootfs
不同。
docker
镜像是由特殊的文件系统叠加而成- 最底端是
bootfs
,并使用宿主机的bootfs
- 第二层是
root
文件系统rootfs
,称之为base imags
- 再往上就是叠加其他的镜像文件(
jdk
,tomcat,...
),最终叠加的所有镜像组成一个统一的文件系统(Union File System
),为这些层提供一个统一的视角。 - 上面叠加的镜像都是只读镜像,不能修改(为了复用),如果想要修改则从一个镜像启动容器时,
Docker
会在最顶层加载一个读写文件系统作为容器,修改完毕后,返回一个新的镜像。
- 最底端是
**
Docker Engine
是一个C/S
架构的应用程序,主要包含下面几个组件;
docker daemon
就是docker
的守护进程即server
端,客户端docker CLI
是通过REST API
进行通信
docker CLI
用来管理容器和镜像,客户端提供一个只读镜像,然后通过镜像可以创建多个容器。
用户不能与server
直接交互,但可以通过与容器这个桥梁来交互。
Docker 架构
Docker使用了C/S体系架构,Docker客户端与Docker守护进程通信,Docker守护进程负责构建,运行和分发Docker容器。Docker客户端和守护进程可以在同一个系统上运行,也可以将Docker客户端连接到远程Docker守护进程。Docker客户端和守护进程使用REST API通过UNIX套接字或网络接口进行通信。
名称 | 说明 |
---|---|
客户端(Client) | Docker 客户端通过命令行或者其他工具使用 Docker API 与 Docker 的守护进程通信。 |
主机(Host) | 一个虚拟的机器用于执行 Docker 守护进程和容器。 |
守护进程(Daemon) | 是Docker服务器端进程,负责支撑Docker 容器的运行以及镜像的管理。 |
容器(Container) | 容器是独立运行的一个或一组应用。镜像相当于类,容器相当于类的实例 |
仓库(Registry) | 用来保存镜像,是代码控制中的代码仓库。 Docker Hub提供了庞大的镜像集合供使用。用户也可以将本地的镜像推送到仓库 |
镜像(Images) | 用于创建 Docker 容器的模板。 镜像是基于联合文件系统的一种层式结构,由一系列指令一步一步构建出来。 |
Docker 安装与启动
Docker
可以运行在MAC
、Windows
、CentOS
、DEBIAN
、UBUNTU
等操作系统上,提供社区版和企业版,我们这里基于CentOS
安装 Docker
。
Docker
从 17.03 版本之后分为 CE
(Community Edition
:社区版) 和 EE
(Enterprise Edition
:企业版)
# 更新yum 源
sudo yum update -Y
# 安装相关工具库
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 设置yum源 阿里云,提升在线 安装 docker 的速度
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum install -y docker-ce # 安装docker
docker -v # 查看docker版本
Linux sudo
命令以系统管理者的身份执行指令,相当于root
亲自执行
设置 阿里云 镜像加速器
docker
从 docker hub
拉取镜像,因为是从国外获取,速度较慢。可以通过配置国内镜像源的方式,从国内获取镜像,提高拉取速度。
直接登录阿里云,选择控制台–>搜索镜像–>选择容器镜像服务–>开通–>找到左侧菜单栏的镜像加速器–>选择CentOS–>复制它提供的代码–>
linux
执行即可
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://to5kngns.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
cat /etc/docker/daemon.json
注意上述配置,小伙伴们需要自己操作一下,不能直接复制执行,每个用户的镜像加速器地址不一样。
如果觉得麻烦,也可以使用下述公开的 镜像加速器,直接修改registry-mirrors
即可。
{
"registry-mirrors": ["https://registry.docker-cn.com","http://f1361db2.m.daocloud.io","http://hub-mirror.c.163.com"]
}
Docker启动与停止命令
systemctl start docker # 启动docker服务
systemctl stop docker # 停止docker服务
systemctl restart docker # 重启docker服务
systemctl status docker # 查看docker服务状态
systemctl enable docker # 设置开机启动docker服务
docker info # 查看docker 信息
Docker常用命令
镜像相关命令
镜像 就是对某些运行环境或者软件打的包,用户可以从 docker
仓库中下载基础镜像到本地,比如开发人员可以从 docker
仓库拉取(下载)一个只包含 centos7
系统的基础镜像,然后在这个镜像中安装jdk
、mysql
、Tomcat
和自己开发的应用,最后将这些环境打成一个新的镜像。
开发人员将这个新的镜像提交给测试人员进行测试,测试人员只需要在测试环境下运行这个镜像就可以了,这样就可以保证开发人员的环境和测试人员的环境 完全一致。
docker images # 查看镜像 hub.docker.com https://c.163.com/hub
docker search 镜像名称[:tag] # 在仓库中搜索需要的镜像
docker pull 镜像名称[:tag] # 从仓库下载镜像到本地,镜像名称格式为 名称:版本号,如果版本号不指定则是最新的版本
docker rmi 镜像id # 根据镜像ID删除
docker images -q # 查看所有镜像ID
docker rmi `docker images -q` #删除所有镜像
执行 docker
相关命令出现如下错误,表示没有权限操作,解决办法,使用 sudo
获取 管理员权限
“Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/images/json: dial unix /var/run/docker.sock: connect: permission denied”
# 启动 docker
docker search nginx # 搜索 nginx 镜像
docker pull nginx # 下载 nginx 镜像
docker images # 查看本地所有镜像
容器相关命令
容器是由镜像运行产生的运行实例。镜像和容器的关系,就如同 Java
语言中类和对象的关系。
docker run [option] 镜像名字[:tag] # 创建与启动容器
docker ps # 查看正在运行的容器
docker ps -a # 查看所有容器
docker exec -it container_name # 进入容器内部
option 参数说明:
-i
:保持容器运行,通常与 -t 一起使用,容器创建后自动进入容器,退出容器后,容器自动关闭
-t
:创建交互式容器,即为容器分配一个伪终端,通常与 -i 一起使用。
-d
:创建一个守护式容器在后台运行,需要 docker exec 命令进入容器,退出后,容器不会关闭
--name
:为创建的容器命名。
-v
:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录)
-p
:表示端口映射,前者是宿主机端口,后者是容器内的映射端口,这样宿主机就可以通过端口访问
守护式容器
如果对于一个需要长期运行的容器来说,我们可以把它创建一个守护式容器。注意:容器名称不能重复
docker run -di --name=nginx -p 8080:80 nginx #创建并启动守护式容器,设置容器名称以及映射端口号
docker exec -it nginx /bin/bash | bash #进入容器,分配终端
ls # 查看容器中的内容,其实就是 linux 目录结构,镜像依赖于 linux 系统
exit # 退出当前容器
交互式容器
以交互式方式创建并启动容器,启动完成后,直接进入当前容器。使用exit命令退出容器。需要注意的是以此种方式启动容器,如果退出容器,则容器会进入停止状态。
#创建并启动名称为 nginx 的交互式容器;下面指令中的镜像名称 nginx 也可以使用镜像id
docker run -it --name=nginx nginx /bin/bash | bash
停止/启动/删除 容器
docker stop 容器名或ID # 停止正在运行的容器
docker start 容器名或ID # 启动容器
docker rm 容器名或ID # 删除容器 如果要删除多个 直接 空格分隔即可
docker rm `docker ps -aq` # 删除所有容器
docker inspect 容器名称或ID # 查看容器信息
文件拷贝 : 将 linux
宿主机中的文件拷贝到容器内
docker cp abc.txt nginx2:/ # 复制abc.txt到nginx2的容器的 / 目录下
docker exec -it nginx2 /bin/bash # 进入nginx2容器
ll # 查看容器 / 目录下文件
#在Linux宿主机器执行复制;nginx2/cba.txt文件复制到 宿主机器的/root目录下
docker cp nginx2:/cba.txt /root # 将文件从容器内拷贝出来到linux宿主机
目录挂载: 可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器。且容器删除后,宿主机中的数据依然存在,不会丢失
mkdir /usr/local/test # 创建linux宿主机器要挂载的目录
# 创建并启动容器nginx3,并挂载linux中的/test目录到容器的/test_container,目录不存在他会自动创建
docker run -di -v /usr/local/test:/usr/local/test_container --name=nginx3 nginx
touch /usr/local/test/def.txt # 在linux下创建文件
docker exec -it nginx3 /bash # 进入容器
ll /usr/local/test_container # 在容器中查看目录中是否有对应文件def.txt
注意:如果你共享的是多级的目录,可能会出现权限不足的提示。 这是因为
CentOS7
中的安全模块selinux
把权限禁掉了,需要添加参数--privileged=true
来解决挂载的目录没有权限的问题。
容器定制内容转为新的镜像使用(了解)
# 容器转为镜像 了解
docker commit 容器ID 镜像名称:版本号 # 保存为一个新的镜像
docker images # 查看是否转换成功
docker save -o 压缩文件名称 镜像名称:版本号 # 把镜像保存为一个压缩文件(my_tomcat.tar),用于传输
docker load -i 压缩文件名称 # 删除原来的镜像,使用压缩文件(my_tomcat.tar)还原镜像
docker images # 查看是否还原成功
docker run -it --name=new_tomcat 镜像名称:版本号 bash # 创建容器运行,目录挂载会失效
Docker应用部署
Nginx部署
# 创建容器,设置端口,目录映射
docker run -di \
--name=nginx \
-p 80:80 \
-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf \
-v $PWD/logs:/var/log/nginx \
-v $PWD/html:/usr/share/nginx/html \
nginx
MySQL部署
docker pull mysql:5.7 # 拉取MySQL 5.7镜像
# 创建容器,设置端口,目录映射
docker run -di \
--name=mysql5.7 \
-p 3306:3306 \
-v $PWD/conf:/etc/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
mysql:5.7
-p
代表端口映射,格式为 宿主机映射端口:容器运行端口
-v
目录挂载,方便宿主机和容器文件操作 **$PWD : **获取 pwd 命令返回的地址
-e
代表添加环境变量MYSQL_ROOT_PASSWORD
是root
用户的远程登陆密码(如果是在容器中使用root
登录的话,那么其密码为空)
docker exec -it mysql5.7 /bin/bash # 进入 mysql 容器
mysql -u root -p # 登录容器里面的mysql
上面创建的时候做了端口映射,则我们可以使用 MySQL 远程客户端进行访问测试。
Tomcat部署
docker pull tomcat # 拉取tomcat镜像
# 创建tomcat容器;并挂载了webapps目录
docker run -di \
--name=mytomcat \
-p 8080:8080 \
-v $PWD:/usr/local/tomcat/webapps \
tomcat
如果出现
WARNING: IPv4 forwarding is disabled. Networking will not work.
则编辑/etc/sysctl.conf
,最后添加net.ipv4.ip_forward=1
, 重启网络:systemctl restart network
在 tomcat
目录下新建一个 index.html
文件,测试访问宿主机的端口号为 8080
的 tomcat
。
Redis部署
docker search redis # 搜索 redis 镜像
docker pull redis:5.0 # 拉取 redis 镜像
docker run -id --name=redis -p 6379:6379 redis:5.0 # 创建 redis 容器,设置端口映射
使用宿主机连接
redis
测试,连接命令:redis-cli.exe -h 192.168.25.128 -p 6379
Dockerfile
在Docker
中创建镜像最常用的方式,就是使用Dockerfile
。Dockerfile
是一个Docker
镜像的描述文件,我们可以理解成火箭发射的A、B、C、D…的步骤。Dockerfile
其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
指令 | 描述 |
---|---|
FROM | 构建新镜像是基于那个镜像 |
MAINTAINER | 镜像维护者姓名或邮箱 |
RUN | 构建镜像时运行的 Shell 命令,也可以是 RUN [“command”,“param1”,“param2”] |
LABEL | 用来做说明的,可以替换MAINTAINER,最终在查看镜像的时候显示 |
COPY | 拷贝文件或目录到镜像中,不会解压缩 |
ADD | 添加文件到镜像中,可以来源于远程服务,会自动解压缩 |
EVN | 设置环境变量 |
VOLUMES | 挂载数据卷,同 docker run -v |
USER | 为 RUN、CMD和 ENTRYPOINT 执行命令指定运行用户 |
EXPOSE | 声明容器运行的时候监听的端口,启动容器时用-p绑定暴露的端口 |
HEALTHCHECK | 容器中的服务健康检查 |
WORKDIR | 为 RUN、CMD、ENTRYPOINT、COPY和ADD设置工作目录,如果没有创建,则自动创建 |
ENTRYPOINT | 运行容器时执行,如果有多个,最后一个生效 |
CMD | 运行容器时执行,如果有多个,则最后一个生效 |
# Dockerfile 案例 springboot-dockerfile
FROM java:8
MAINTAINER cdhong <cdhing.it@qq.com>
ADD springboot-demo-1.0.0-SNAPSHOT.jar app.jar
EXPOSE 8080
CMD java -jar app.jar
docker build -f ./springboot-dockerfile -t app:1.0 . # 根据 dockerfile 构建镜像 ,. 表示构建目录
docker run -id -p 9000:8080 app
搭建一个 JavaWeb 应用的镜像Dockerfile
FROM centos:7
MAINTAINER cdhong.it<cdhong.it@qq.com>
# Install tools
RUN yum install vim -y
# Install java8
ADD jdk-8u251-linux-x64.tar.gz /usr/local
RUN mv /usr/local/jdk1.8.0_251 /usr/local/java
ENV JAVA_HOME /usr/local/java
# ENV PATH $PATH:$JAVA_HOME/bin
# Install Tomcat8
ADD apache-tomcat-8.5.43.tar.gz /usr/local
RUN mv /usr/local/apache-tomcat-8.5.43 /usr/local/tomcat8
# expose ports
EXPOSE 8080
#workspace
WORKDIR /usr/local/
# run shell
ENTRYPOINT /usr/local/tomcat/bin/startup.sh && tail -F /usr/local/tomcat/logs/catalina.out
docker build -t my_tomcat:1.0 . # 构建新镜像
# 创建容器
docker run -it --name=tomcate -p 8080:8080 \
-v $PWD/webapps/:/usr/local/tomcat/webapps/ \
-v $PWD/logs/:/usr/local/tomcat/logs/ \
--privileged=true \
my_tomcat:1.0
# 验证
docker exec 容器ID java -version # 查看 java 版本信息
服务编排-Docker Compose
Docker Compose
是通过python
编写的Docker
的服务编排工具,主要用来构建基于Docker
的复杂应用,Compose
通过一个配置文件来管理多个Docker
容器,非常适合组合使用多个容器进行开发的场景。
- 通过
dockerfile
只能生成单一的容器(称之为service
)。在实际开发的环境中,没有单独存在的应用,我们会把多个应用搭建在一起形成一个完整的系统(称之为project
)。 Compose
它允许用户通过一个单独的docker-compose.yml
模板文件来定义一组相关联的应用容器为一个项目。
使用步骤:
- 利用
Dockerfile
定义运行环境镜像 - 使用
docker-compose.yml
定义组件应用的各个服务模板 - 运行
docker-compose up
启动应用
文件模板节点
一份标准配置文件应该包含 version
、services
、networks
三大部分
文件节点 | 说明 | 文件节点 | 说明 |
---|---|---|---|
version | 指定 Docker Compose 版本 | services | 所有容器服务的父节点 |
restart | 开机是否自动启动 | volumes | 数据卷(宿主机路径 : 容器内路径) |
image | 指定镜像名 | command | 覆盖容器启动后默认执行的命令 |
ports | 端口开放映射 | environment | 环境变量 |
networks | 加入指定网络 | container_name | 为自定义容器命名,不使用默认 |
build | 指定Dockerfile,up 启动时执行构建任务 | depends_on | 解决容器依赖问题,指定启动顺序 |
# 安装 docker-compose ,以编译好的二进制包方式安装在 Linux 系统中
curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# curl: (56) TCP connection reset by peer 访问不到docker官方镜像,或者github访问太慢,可以用daocloud下载
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose # 设置 docker-compose 执行权限
docker-compose --version # 查看 docker-compose 版本信息
rm /usr/local/bin/docker-compose # 卸载 docker-compose,删除二进制文件即可
mkdir docker-compose # 创建文件夹
vim docker-compose.yml # 文件名固定,不能自定义
version: '3.1'
services:
mysql:
restart: always
image: mysql:5.7.22
container_name: mysql
ports:
- 3306:3306
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: root
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
volumes:
- $PWD/mysql/conf:/etc/mysql/conf.d
- $PWD/mysql/logs:/logs
- $PWD/mysql/data:/var/lib/mysql
tomcat:
restart: always
image: tomcat
container_name: tomcat
ports:
- 8080:8080
volumes:
- $PWD/tomcat/webapps:/usr/local/tomcat/webapps
environment:
TZ: Asia/Shanghai
docker-compose up # 构建启动所有服务
docker-compose down # 停止移除所有服务
# 把 准备好的项目添加到 webapp 中,tomcat 会自动解压
# 把准备好的 sql 脚本登录 mysql 执行
# 在 宿主机 上通过浏览器访问 http://192.168.25.128:8080/项目名/requestMapper
命令 | 描述 |
---|---|
docker-compose up -d nginx | 构建建启动nignx容器 |
docker-compose exec nginx bash | 登录到nginx容器中 |
docker-compose down | 删除所有容器,镜像 |
docker-compose ps | 显示所有容器 |
docker-compose restart nginx | 重新启动nginx容器 |
docker-compose config -q | 验证(docker-compose.yml)文件配置 |
docker-compose pause nginx | 暂停nignx容器 |
docker-compose unpause nginx | 恢复ningx容器 |
docker-compose rm nginx | 删除容器(删除前必须关闭容器) |
docker-compose stop nginx | 停止nignx容器 |
docker-compose start nginx | 启动nignx容器 |
私有仓库
私有仓库搭建
docker pull registry # 拉取私有仓库镜像
docker run -id --name register -p 5000:5000 register # 启动私有仓库容器,通过 http://私有仓库服务器ip:5000/v2/_catalog 访问测试
vim /etc/docker/daemon.json # 修改 daemon.json 添加一个 key ,让 docker 信任私有仓库地址 {"insecure-registries":["私有仓库服务器IP:5000"]}
systemctl restart docker # 重启 docker 服务
docker start registry # 启动私有仓库容器
将镜像上传到私有仓库
docker tag centos:7 私有仓库服务器IP:5000/centos:7 # 标记镜像为私有仓库镜像
docker push 私有仓库服务器IP:5000/centos:7 # 上传标记的镜像
从私有仓库拉取镜像
docker pull 私有仓库服务器IP:5000/centos:7 # 拉取