Docker
1. 什么是Docker
项目部署的问题
- 大型项目组件较多,运行环境较为复杂,部署时会碰到一些问题
- 依赖关系升级,容易出现兼容性问题
- 开发,测试,生产环境有差异
Docker如何解决依赖的兼容问题的?
- Docker允许开发中将应用、依赖、函数库、配置一起打包,形成可移植镜像
- Docker应用运行在容器中,使用沙箱机制,相互隔离
Docker如何解决开发、测试、生产环境有差异的问题
- Docker镜像中包含完整运行环境,包含系统函数库,仅依赖系统的Linux内核,因此可以在任意Linux操作系统上运行
总结
- Docker是一个快速交付应用、运行应用的技术
- 可以将程序及其依赖、运行环境一起打包为一个镜像,可以迁移到任意Linux操作系统
- 运行时利用沙箱机制形成隔离容器,各个应用互不干扰
- 启动、移除都可以通过一行命令完成,方便快捷
2. Docker和虚拟机的差别
- docker是一个系统进程,虚拟机是在操作系统中饿操作系统
- docker体积小、启动速度快、性能好;虚拟机体积大、启动速度满、性能一般
3. Docker架构
- 镜像:将应用程序及其依赖、环境、配置打包在一起
- 容器:镜像运行起来就是容器,一个镜像可以运行多个容器
- Docker结构
- 服务端:接收命令或远程请求,操作镜像或容器
- 客户端:发送命令或请求到Docker服务端
- DockerHub :一个镜像托管的服务器,类似的还有阿里云镜像服务,统称为DockerRegistry
4. Docker的安装
- 请参考这篇文章Centos7安装Docker
5. Docker基本操作
5.1 镜像命令
- docker images 查看镜像
- docker rmi 删除镜像
- docker pull 拉取镜像
- docker push
- docker save 保存镜像为tar文件
- docker load 读取tar文件,变成镜像
5.2 容器命令
- docker exec 进入容器执行命令
- docer logs 查看容器运行的日志 添加-f参数可以持续查看日志
- docker ps 查看所有运行的容器及状态 添加-a参数查看所有状态的容器
- docker pause 暂停
- docker unpause 恢复运行
- docker stop 停止
- docker start 新运行一个
- docker rm 删除指定容器(不能删除运行中的容器,除非添加-f参数)
- 练习1
创建运行一个nginx容器
docker run --name containerName -p 80:80 -d nginx
命令解读
docker run:创建并运行一个容器
--name:给容器起一个名字,比如叫做mn
-p:将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口
-d:后台运行容器
nginx:镜像名称,例如nginx
- 练习二:进入Nginx容器,修改HTML文件内容
进入容器
docker exec -it mn bash
命令解读
docker exec:进入容器内部,执行一个命令
-it:给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互
mn:要进入容器的名称
bash;进入容器后执行的命令,bash是一个linux终端交互命令
进入Nginx的HTML所在目录/usr/share/nginx/html
cd /usr/share/nginx/html
修改index.html的内容
sed -i 's#Welcome to nginx#传智播客欢迎您#g' index.html
sed -i 's#<head>#<head><meta charset="utf-8">#g' index.html
- 练习三:创建并运行一个redis容器,并且支持数据持久化->进入redis容器,并执行redis-cli客户端命令,存入num=666
创建运行一个redis容器
docker run --name mr -p 6379:6379 -d redis-server --appendonly yes
进入容器
docker exec -it mr bash
进入redis
redis-cli
存储数据
set num 666
获取数据
get num
5.3 数据卷命令
-
作用:将容器和数据分离,解耦合,方便操作容器内数据,保证数据安全
-
docker volume [COMMAND]------>docker volume命令是数据卷操作,根据命令后跟随的command来确定下一步的操作
-
create:创建一个volume
-
inspect:显示一个或多个volume的信息
-
ls:列出所有的volume
-
prune:删除未使用的volume
-
rm:删除一个或多个指定的volume
-
练习一:挂载数据卷
# 运行容器时使用-v参数挂载数据卷
docker run --name mn -p 80:80 -v html:/usr/share/nginx/html -d nginx
# 查看html数据卷的位置
docker volume inspect html
#进入该目录
cd /var/lib/docker/volumes/html_data
#修改文件
vi index.html
*如果容器运行时volume不存在,会自动被创建出来
- 练习二:创建并运行一个mysql容器,将宿主机目录直接挂载到容器
创建镜像
docker load -i mysql.tar
创建两个目录
/tmp/mysql/data
/tmp/mysql/conf
将配置文件cnf放在conf目录下
进行挂载
docker run --name mysql -e MYSQL_ROOT_PASSWORD=123 -P 3306:3306
-V /tmp/mysql/conf/hmy.conf:/etc/mysql/conf.d/hmy.cnf
-v /tmp/mysql/data:/var/lib/mysql
-d mysql:5.7.25
数据卷挂载和目录挂载的区别
- 数据卷挂载耦合度低,由docker来管理目录,但是目录较深,不好找
- 目录挂载耦合度高,需要我们自己管理目录,不过目录容易寻找查看
6.自定义镜像
6.1:镜像结构
- 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成
6.2: Dockerfile
-
案例:基于Ubuntu镜像构建一个新镜像
-
创建docker-demo.jar文件夹
-
将docker-demo.jar、dockerfile、jdk8.tar.gz放入docker-demo.jar文件夹下
-
# dockerfile文件内容 # 指定基础镜像 FROM ubuntu:16.04 # 配置环境变量,JDK的安装目录 ENV JAVA_DIR=/usr/local # 拷贝jdk和java项目的包 COPY ./jdk8.tar.gz $JAVA_DIR/ COPY ./docker-demo.jar /tmp/app.jar # 安装JDK RUN cd $JAVA_DIR \ && tar -xf ./jdk8.tar.gz \ && mv ./jdk1.8.0_144 ./java8 # 配置环境变量 ENV JAVA_HOME=$JAVA_DIR/java8 ENV PATH=$PATH:$JAVA_HOME/bin # 暴露端口 EXPOSE 8090 # 入口,java项目的启动命令 ENTRYPOINT java -jar /tmp/app.jar
-
运行命令 docker bulid -t javaweb:1.0 构建镜像
-
启动:docker run --name web -p 8090:8090 -d javaweb:1.0
-
-
案例:基于java:8-alpine镜像,将一个java项目构建为镜像
-
创建docker-demo.jar文件夹,并新建文件dockerfile
-
将docker-demo.jar放入docker-demo.jar文件夹下
-
# dockerfile文件内容 # 指定基础镜像 FROM java:8-alpine # 拷贝jdk和java项目的包 COPY ./docker-demo.jar /tmp/app.jar # 暴露端口 EXPOSE 8090 # 入口,java项目的启动命令 ENTRYPOINT java -jar /tmp/app.jar
-
使用docker bulid命令构建镜像
-
使用docker run创建容器并运行
-
7. DockerCompose
- 作用:帮助我们快速部署分布式应用,无需一个个微服务去构建镜像和部署
案例:将之前学习的cloud-demo微服务集群利用DockerCompose
- 步骤一:
cloud-demo:
- gateway
- app.jar
- Dockerfile
- mysql
- conf
- hmy.cnf
- data
- ...
- order-service
- app.jar
- Dockerfile
- user-service
- app.jar
- Dockerfile
- docker-compose.yml
微服务打包并按照如上目录结构排列
Dockerfile文件内容
FROM java:8-alpine
COPY ./app.jar /tmp/app.jar
ENTRYPOINT java -jar /tmp/app.jar
hmy.cnf文件内容
[mysqld]
skip-name-resolve
character_set_server=utf8
datadir=/var/lib/mysql
server-id=1000
docker-compose.yml文件内容
version: "3.2"
services:
nacos:
image: nacos/nacos-server
environment:
MODE: standalone
ports:
- "8848:8848"
mysql:
image: mysql:5.7.25
environment:
MYSQL_ROOT_PASSWORD: 123
volumes:
- "$PWD/mysql/data:/var/lib/mysql"
- "$PWD/mysql/conf:/etc/mysql/conf.d/"
userservice:
build: ./user-service
orderservice:
build: ./order-service
gateway:
build: ./gateway
ports:
- "10010:10010"
- 步骤二:
运行docker-compose up -d命令进行部署
- 步骤三
docker ps 查看运行状态
如果有未启动成功的项目,则需要重新启动
docker-compose restart [项目名]