Docker概述:
容器是什么?
容器就是运行环境和,容器基础镜像的集合;
容器与虚拟机的区别
**启动速度:**每个虚拟都机是一个完整的操作系统包括操作系统和内核,所以它是一个重量级的系统;而容器是轻量级的,因为容器只打包了操作系统的基础文件和库文件、还有应用程序及所有的依赖,他的运行速度就如同在系统中创建一个进程一样快,所以启动速度较快。
**运行性能:**由于虚拟机增加了虚拟化层用于虚拟化硬件,势必会增加一定的开销,所以运行性能有所损失;而容器是直接运行在物理操作系统上的,他本身与系统上其他进程并没有太大区别,所以运行性能是接近原生的。
**磁盘占用:**虚拟机是一个完整的操作系统,是 GB 级别的,而容器只包含了一些系统启动的必要组件和程序依赖,是 MB 级别的。
**数量:**运行一个操作系统的开销较大,运行一个进程的开销较小,同样的服务器资源可以运行更多的容器。
**隔离性:**虚拟机是一个完整的操作系统级别的隔离,要比容器好很多;容器是进程级别的隔离,隔离的不彻底,因为多个容器之间使用的是同一个宿主机的操作系统内核。
**封装速度:**虚拟机封装会包含操作系统,封装速度比较慢,容器只封装操作系统的基础文件和库文件、应用程序、依赖,封装速度较快。
总结:点击查看【bilibili】
Docker 和容器的关系
容器是一种虚拟化技术,docker 是实现容器的一种工具,我们称它为容器引擎; 可以驱动容器的引擎还有 podman、containerd 等,docker 是目前市面上应用范围最广的一种容器引擎。
自己构建一个容器:
构建镜像需要使用 dockerfile 文件,我们以 Nginx 为例,编写一个 Nginx 镜像的 dockerfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 FROM centos:7.9.2009 WORKDIR /opt ADD nginx-1.24.0.tar.gz /opt RUN yum install -y nc net-tools gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel && \ yum clean all && \ rm -rf /tmp/* rm -rf /var/cache/yum/* && \ cd /opt/nginx-1.24.0 && \ ./configure --user=nobody --group=nobody --prefix=/opt/nginx --with-http_gzip_static_module --with-http_ssl_module --with-stream && \ make && make install && \ rm -rf /opt/nginx-1.24.0 CMD /opt/nginx/sbin/nginx && tail -f /dev/null
构建镜像
1 2 3 4 5 6 # 在 dockerfile 同目录下执行命令 docker build -t nginx:v2 . 注释: -t #构建镜像的名称 . #表示 dockerfile 文件在当前目录下
构建后的镜像名为 nginx:v2 ,在创建容器时可以这样使用:
1 docker run -f nginx_test nginx:v2
镜像服务器:
提供存储、管理Docker镜像的服务器,被称为DockerRegistry,可以翻译为镜像仓库。DockerHub网站是官方仓库,阿里云、华为云会提供一些第三方仓库,我们也可以自己搭建私有的镜像仓库。
1 2 3 4 5 # Docker开机自启 systemctl enable docker # Docker容器开机自启 docker update --restart=always [容器名/容器id]
镜像:
之前我们说过,镜像之所以能让我们快速跨操作系统部署应用而忽略其运行环境、配置,就是因为镜像中包含了程序运行需要的系统函数库、环境、配置、依赖。 因此,自定义镜像本质就是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成。
1.Linux-ubuntu20.04 docker的镜像加速配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $ sudo vim /etc/docker/daemon.json { "registry-mirrors" : ["https://docker.mirrors.ustc.edu.cn" ,"https://hub-mirror.c.163.com/" ,"https://reg-mirror.qiniu.com" ,"https://registry.docker-cn.com" ]} sudo systemctl reload docker sudo systemctl restart docker sudo docker info Registry Mirrors: https://docker.mirrors.ustc.edu.cn/ https://hub-mirror.c.163.com/ https://reg-mirror.qiniu.com/ https://registry.docker-cn.com/
2.相关概念:
容器(Container):容器是Docker中运行应用程序的实例。它们是基于镜像创建的,可以独立运行,并且具有自己的文件系统、进程空间和网络接口。容器提供了一个轻量级、可移植和隔离的环境,使应用程序可以在不同的计算机或环境中一致地运行。
镜像(Image):镜像是Docker中用于创建容器的模板。它包含了一个完整的文件系统,其中包括应用程序所需的所有文件、库和依赖项。镜像是只读的,可以从一个基础镜像构建,然后通过在其上应用更改和配置来定制。镜像是构建和分发应用程序的基本单元,可以在不同的环境中重复使用。
仓库(Repository):仓库是用于存储和共享Docker镜像的地方。它类似于代码仓库,可以存储多个镜像,并提供版本控制和标签管理。Docker Hub是一个公共仓库,其中包含了大量的官方和社区维护的镜像。此外,你也可以创建私有仓库来存储和管理自己的镜像。
常用的命令:
一张脑图整理Docker常用命令-腾讯云开发者社区-腾讯云 Docker最常见的命令就是操作镜像、容器的命令,详见官方文档: https://docs.docker.com/ 1.从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:
1 $ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
1 docker run -it --rm ubuntu:18.04 bash以交互式启动一个容器,如果启动后想退出,输入exit 就可以了
Docker部署Mysql:
mysql中的数据卷是由容器运行时创建的卷,称为匿名卷Docker 安装 MySQL | 菜鸟教程
挂载数据卷以及配置文件:
虽然官网上说默认配置文件在/etc/mysql/my.cnf但是有些镜像的配置文件实际位置不确定,不如我的默认配置文件在/etc/my.cnf,所以创建临时镜像查询默认配置文件的位置,然后复制出来,用来绑定本地配置文件。
1. 为了获取默认mysql配置文件,创建一个临时容器
每个人部署的 MySQL 内,可能文件路径不一致。我们可以先创建个测试的 MySQL 容器,然后再根据查找出的文件具体路径位置,重新创建我们符合我们需求的 MySQL 容器,命令如下:
1 2 3 4 docker run --name mysqltest \ -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root \ -d mysql
进入Docker容器内:
1 docker exec -it mysqltest bash
找到配置文件的默认位置。
1 2 3 4 5 6 7 # 查找Docker内,MySQL配置文件my.cnf的位置 mysql --help | grep my.cnf # 显示如下,意思是路径按优先排序,会是在以下路径里: order of preference, my.cnf, $MYSQL_TCP_PORT, /etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf # 配置文件的路径不一定都一样,有些博客介绍的位置是在/etc/my.cnf。而Ubuntu系统上,实际存在位置是在/etc/mysql/my.cnf
创建本地路径并挂载Docker内数据
接下来,我们需要在物理机上,创建指定好一个数据和配置文件的挂载路径。 创建两个文件夹存放mysql的配置文件和数据
1 2 mkdir -p /docker/mysql/config && mkdir -p /docker/mysql/data
创建好本地的挂载数据路径后,我们再将临时容器里 MySQL 的配置文件复制到该路径。日后需改配置,直接在挂载路径的配置文件上修改即可。
1 2 docker cp mysqltest:/etc/my.cnf /docker/mysql/config/
创建 MySQL 容器并启动
1 2 3 4 5 6 7 8 docker run \ --name mysql \ -v /docker/mysql/config/my.cnf:/etc/my.cnf \ -v /docker/mysql/data:/var/lib/mysql \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=123 \ --restart=on-failure:3 \ -d mysql:8
MySQL8.0设置远程访问权限
1 2 3 # 进入容器 docker exec -it mysql bash
登录MySQL
选择 mysql 数据库
在 mysql 数据库的 user 表中查看当前 root 用户的相关信息
1 2 select host, user, authentication_string, plugin from user;
执行完上面的命令后会显示一个表格 查看表格中 root 用户的 host,默认应该显示的 localhost,只支持本地访问,不允许远程访问。
授权 root 用户的所有权限并设置远程访问
1 2 GRANT ALL ON *.* TO 'root'@'%';
GRANT ALL ON 表示所有权限,% 表示通配所有 host,可以访问远程。
刷新权限
查看 root 用户的 host
1 2 select host, user, authentication_string, plugin from user;
再次执行步骤 2,root 用户的 host 已经变成 %,说明我们的修改已经成功,可以远程访问了。 注意事项
1. 针对现有数据库创建容器
如果您使用mysql已经包含数据库的数据目录启动容器实例,$MYSQL_ROOT_PASSWORD则应从运行命令行中省略 该变量;
Docker部署nginx:
nginx镜像只包括了nginx运行所需要的资源,当我们想要修改nginx中的index.html的时候,在该容器中无法用vi等编辑器修改;因为nginx镜像中没有vi等编辑器的资源。如果我们想要修改index.html的时候可以通过数据卷的方式修改; 挂载:
1 docker run -d -p 80:80 -v html:/usr/share/nginx/html --name my-nginx nginx
这里的html是我们的数据卷,是一个虚拟目录;/usr/share/nginx/html是一个映射容器内的目录;
数据卷:
数据卷只是虚拟的目录只是当成件容器内的目录和主机目录联系起来。
自定义镜像:
网络:
IDEA运行Docker
入门:https://www.cnblogs.com/mayhot/p/15904506.html Idea使用Docker部署SpringBoot项目_idea docker springboot-CSDN博客 1.配置pom.xml的build:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> <!--使用docker-maven-plugin插件--> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>1.0.0</version> <!--将插件绑定在某个phase执行--> <executions> <execution> <id >build-image</id> <!--用户只需执行mvn package ,就会自动执行mvn docker:build--> <phase>package</phase> <goals> <goal>build</goal> </goals> </execution> </executions> <configuration> <!--指定生成的镜像名--> <imageName>zrs/${project.artifactId} </imageName> <!--指定标签--> <imageTags> <imageTag>latest</imageTag> </imageTags> <!-- 指定 Dockerfile 路径--> <dockerDirectory>${project.basedir} </dockerDirectory> <!-- 指定远程 docker api地址,其中指定的ip地址是远程主机的ip地址, 2375是Docker监听的端口--> <dockerHost>http://192.168.44.130:2375</dockerHost> <!-- 这里是复制 jar 包到 docker 容器指定目录配置 --> <resources> <resource> <targetPath>/</targetPath> <!--jar 包所在的路径 此处配置的 即对应 target 目录--> <directory>${project.build.directory} </directory> <!-- 需要包含的 jar包 ,这里对应的是 Dockerfile中添加的文件名 --> <include>${project.build.finalName} .jar</include> </resource> </resources> </configuration> </plugin> </plugins> </build>
Dockerfile的书写:位置在项目根路径下:
1 2 3 4 5 6 7 8 9 10 11 12 FROM openjdk:17 LABEL maintainer="reda" VOLUME /tmp COPY ./target/DockerDome-0.0.1-SNAPSHOT.jar pms.jar RUN sh -c 'touch /pms.jar' ENTRYPOINT [ "java" , "-jar" , "/pms.jar" ]
Dockerfile:
由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以Docker就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给Docker去执行即可。 而这种记录镜像结构的文件就称为Dockerfile ,其对应的语法可以参考官方文档:https://docs.docker.com/engine/reference/builder/ 其中的语法比较多,比较常用的有:
指令
说明
示例
FROM
指定基础镜像
FROM centos:6
ENV
设置环境变量,可在后面指令使用
ENV key value
COPY
拷贝本地文件到镜像的指定目录
COPY ./xx.jar /tmp/app.jar
RUN
执行Linux的shell命令,一般是安装过程的命令
RUN yum install gcc
EXPOSE
指定容器运行时监听的端口,是给镜像使用者看的
EXPOSE 8080
ENTRYPOINT
镜像中应用的启动命令,容器运行时调用
ENTRYPOINT java -jar xx.jar
例如,要基于Ubuntu镜像来构建一个Java应用,其Dockerfile内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 FROM ubuntu:16.04 ENV JAVA_DIR=/usr/localENV TZ=Asia/ShanghaiCOPY ./jdk8.tar.gz $JAVA_DIR / COPY ./docker-demo.jar /tmp/app.jar RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN cd $JAVA_DIR \ && tar -xf ./jdk8.tar.gz \ && mv ./jdk1.8.0_144 ./java8 ENV JAVA_HOME=$JAVA_DIR/java8ENV PATH=$PATH:$JAVA_HOME/binEXPOSE 8080 ENTRYPOINT ["java" , "-jar" , "/app.jar" ]
同学们思考一下:以后我们会有很多很多java项目需要打包为镜像,他们都需要Linux系统环境、JDK环境这两层,只有上面的3层不同(因为jar包不同)。如果每次制作java镜像都重复制作前两层镜像,是不是很麻烦。 所以,就有人提供了基础的系统加JDK环境,我们在此基础上制作java镜像,就可以省去JDK的配置了:
1 2 3 4 5 6 7 8 9 FROM openjdk:11.0 -jre-busterENV TZ=Asia/ShanghaiRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone COPY docker-demo.jar /app.jar ENTRYPOINT ["java" , "-jar" , "/app.jar" ]
构建镜像:
当Dockerfile文件写好以后,就可以利用命令来构建镜像了。 将课前资料提供的docker-demo.jar包以及Dockerfile拷贝到虚拟机的/root/demo目录:
1 2 3 4 cd /root/demo docker build -t docker-demo:1.0 .
命令说明:
docker build : 就是构建一个docker镜像
-t docker-demo:1.0 :-t参数是指定镜像的名称(repository和tag)
. : 最后的点是指构建时Dockerfile所在路径,由于我们进入了demo目录,所以指定的是.代表当前目录,也可以直接指定Dockerfile目录:
1 2 docker build -t docker-demo:1.0 /root/demo
运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 docker run -d --name dd -p 8080:8080 docker-demo:1.0 dps CONTAINER ID IMAGE PORTS STATUS NAMES 78 a000447b49 docker-demo:1.0 0.0 .0.0 :8080 ->8080 /tcp, :::8090 ->8090 /tcp Up 2 seconds ddf63cfead8502 mysql 0.0 .0.0 :3306 ->3306 /tcp, :::3306 ->3306 /tcp, 33060 /tcp Up 2 hours mysql curl localhost:8080 /hello/count <h5>欢迎访问黑马商城, 这是您第1 次访问<h5>
网络:
13-Docker网络
容器的网络IP其实是一个虚拟的IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个IP,而在部署时很可能MySQL容器的IP会发生变化,连接会失败。
自定义网络
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 docker network create hmall docker network ls NETWORK ID NAME DRIVER SCOPE 639 bc44d0a87 bridge bridge local403 f16ec62a2 hmall bridge local0 dc0f72a0fbb host host localcd8d3e8df47b none null local docker network connect hmall mysql --alias db docker network connect hmall dd docker exec -it dd bash ping db PING db (172.18 .0.2 ) 56 (84 ) bytes of data. 64 bytes from mysql.hmall (172.18 .0.2 ): icmp_seq=1 ttl=64 time=0.070 ms64 bytes from mysql.hmall (172.18 .0.2 ): icmp_seq=2 ttl=64 time=0.056 msping mysql PING mysql (172.18 .0.2 ) 56 (84 ) bytes of data. 64 bytes from mysql.hmall (172.18 .0.2 ): icmp_seq=1 ttl=64 time=0.044 ms64 bytes from mysql.hmall (172.18 .0.2 ): icmp_seq=2 ttl=64 time=0.054 ms
在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身
在同一个自定义网络中的容器,可以通过别名互相访问
docker安装并启动服务后,会在宿主机中添加一个虚拟网卡。
作用:
容器间的互联和通信以及端口映射
容器IP变动时候可以通过服务名直接网络通信而不受到影响
Docker 网络模式
网络模式
简介
使用方式
bridge
为每一个容器分配、设置IP等,并将容器连接到一个docker0
虚拟网桥,默认为该模式
--network bridge
host
容器将不会虚拟出自己的网卡、配置自己的IP等,而是使用宿主机的IP和端口
--network host
none
容器有独立的 Network namespace,但并没有对齐进行任何网络设置,如分配veth pari
和 网桥连接、IP等
--network none
container
新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP、端口范围等
--network container:NAME或者容器ID
docker0
Docker 服务默认会创建一个docker0
网桥(其上有一个docker0
内部接口),该桥接网络的名称为 docker0
,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。 Docker默认指定了docker0
接口的IP地址和子网掩码,让主机和容器之间可以通过网桥互相通信。
Docker可视化管理工具:
1Panel:
设置云服务器的安全组放行其端口
跟着下面的文档安装即可:
在线安装 - 1Panel 文档
docker-compose
docker-copose 介绍
14-Docker-compose容器编排
docker-compose 是一个容器编排工具(自动化部署、管理);
它用来在单台 Linux 服务器上运行多个 Docker 容器;
docker-compose 使用YAML文件来配置所有需要运行的 Docker 容器,该 YAML 文件的默认名称为 docker-compose.yml
docker-compose 安装
1 2 3 4 curl -L "https://github.com/docker/compose/releases/download/v2.18.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose docker-compose version
使用 docker-compose 启动一个容器
1 2 3 4 5 6 7 8 9 version: '2.1' services: nginx: image: nginx:latest container_name: nginx_test ports: - 8080:80 volumes: - /opt/nginx:/opt/nginx/html
启动容器 在 docker-compose 所在目录执行
Dockerdocker-compose 命令总结
启动容器
停止容器
重启容器
重载 docker-compose.yml
1 docker-compose up --force-recreate -d
docker-compose 创建多个容器
使用 docker-compose 启动 Nginx 和 Redis 两个容器: docker-compose.yml 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 version: '2.1' services: nginx: image: nginx:latest container_name: nginx_host1 ports: - 8081 :80 volumes: - /opt/nginx:/opt/nginx/html networks: - host1-network redis: image: redis:latest container_name: redis_host1 ports: - 63790 :6379 networks: - host1-network networks: host1-network: driver: bridge ipam: driver: default config: - subnet: 192.168 .11 .0 /24 gateway: 192.168 .11 .254
参数: networks 定义容器网络,host1-network 为定义的网络名称, config 网络配置,subnet 代表网段,gateway 代表网关。 执行创建命令
可以看到成功创建了 Nginx 和 Redis 两个容器 可以进入 nginx_host1 容器查看一下端口和 IP 上图可见,nginx_host1 的 IP 为:192.168.11.2 ,符合 docker-compose 中定义的 192.168.11.0/24 网段; 如果访问 Redis 可以直接使用docker-compose 定义的 redis_host1 容器名访问即可。12-Docker发布微服务
容器启动顺序:
depends_on
只能保证容器的启动和销毁顺序,不能确保依赖的容器是否ready。
1 2 3 4 5 6 7 8 9 10 11 version: "3.9" services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres
在这个例子中,depends_on
只能保证web
容器在db
,redis
之后启动,不会关注他们的状态是否启动完成或准备就绪。 要确保应用服务在数据库初始化完成后再启动,需要配合[condition](https://docs.docker.com/compose/compose-file/#depends_on)
和[healthcheck](https://docs.docker.com/compose/compose-file/#healthcheck)
使用。
1 2 3 4 5 6 7 8 9 10 11 12 services: web: build: . depends_on: db: condition: service_healthy redis: condition: service_started redis: image: redis db: image: postgres
ondition
有三种状态:service_started
容器已启动service_healthy
容器处于健康状态service_completed_successfully
容器执行完成且成功退出(退出状态码为0) 我们来改造一下我们自己的docker-compose.yaml文件,完整例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 services: ruoyi-app: # docker run --name ruoyi-app \ # -p 8080:8080 \ # --network ruoyi-net \ # -v /home/app/ruoyi-admin.jar:/usr/local/src/ruoyi-admin.jar \ # -d openjdk:8u342-jre \ # java -jar /usr/local/src/ruoyi-admin.jar image: openjdk:8u342-jre restart: always ports: - 8080:8080 networks: - ruoyi-net volumes: - /home/app/ruoyi-admin.jar:/usr/local/src/ruoyi-admin.jar command: [ "java", "-jar", "/usr/local/src/ruoyi-admin.jar" ] healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080"] interval: 10s timeout: 5s retries: 5 start_period: 10s depends_on: ruoyi-db: condition: service_healthy ruoyi-db: # docker run --name ruoyi-db -p 3303:3306 \ # --network ruoyi-net \ # -v ruoyi-data:/var/lib/mysql \ # -v /home/app/sql:/docker-entrypoint-initdb.d \ # -e MYSQL_DATABASE=ry \ # -e MYSQL_ROOT_PASSWORD=123456 \ # -d mysql:5.7 \ # --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --skip-character-set-client-handshake image: mysql:5.7 environment: - MYSQL_DATABASE=ry - MYSQL_ROOT_PASSWORD=123456 volumes: - ruoyi-data:/var/lib/mysql - /home/app/sql:/docker-entrypoint-initdb.d networks: - ruoyi-net command: [ "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci", "--skip-character-set-client-handshake" ] healthcheck: test: ["CMD", 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', '-p$$MYSQL_ROOT_PASSWORD'] interval: 10s timeout: 5s retries: 5 start_period: 10s volumes: ruoyi-data: networks: ruoyi-net: