其实就是对进程的封装,使得它与其他进程独立,并且独立于宿主,也称为容器
Docker是对容器的封装
那他与传统的虚拟机有什么区别呢?
传统虚拟需要虚拟出一套硬件,在其上面运行一个完整的操作系统,在这个系统上运行所需应用进程;而容器内的应用程序直接运行在宿主的内核,容器内没有直接点内核,也没有硬件虚拟。所以容器要比传统的虚拟机更加轻便。
那它有什么优势呢?
高效的利用系统的资源
快速的启动时间
一致的运行环境
持续交付和部署
轻松的迁移、维护和扩展
三个要素是啥?
镜像、容器、仓库
一、Docker概述
1.1 Docker 为什么出现?
-
解决环境差异问题:开发、测试、生产环境不一致,导致应用部署困难。
-
提高资源利用率:传统虚拟机资源占用大,Docker容器更轻量,能更高效地利用硬件资源。
1.2 Docker历史
-
2013年,Docker项目启动。
-
2014年,Docker 1.0版本发布,标志着Docker技术的成熟。
1.3 能做什么
-
应用打包:将应用及其依赖打包成一个容器,确保在任何环境下都能正常运行。
-
环境隔离:为每个应用提供独立的运行环境,避免依赖冲突。
-
快速部署:容器启动迅速,能快速部署应用。
-
持续集成与交付:与CI/CD流程结合,实现自动化测试和部署。
二、Docker安装
2.1 基本组成
-
Docker客户端:用户通过命令行工具与Docker守护进程通信。
-
Docker守护进程:负责构建、运行和管理容器。
-
Docker镜像:只读的模板,包含应用程序及其依赖。
-
Docker容器:镜像的运行实例,提供隔离的运行环境。
-
Docker仓库:存储和管理Docker镜像的地方。
2.2 安装Docker
-
Linux:使用包管理工具安装,如
apt
或yum
。 -
Windows:安装Docker Desktop for Windows。
-
Mac:安装Docker Desktop for Mac。
2.3 阿里云镜像加速
-
配置镜像加速可以提高镜像下载速度,特别是在国内网络环境下。
-
配置方法:在Docker守护进程配置文件中添加镜像加速地址。
2.4 回顾hello-world流程
-
拉取
hello-world
镜像:docker pull hello-world
-
运行容器:
docker run hello-world
2.5 底层原理
-
Docker是怎么工作的?
-
Docker利用Linux内核的Cgroups和NameSpace技术,对进程进行封装隔离。
-
容器共享宿主机的操作系统内核,但彼此隔离。
-
-
Docker为什么比VM(虚拟机)快?
-
虚拟机需要完整的操作系统,占用大量资源。
-
Docker容器共享宿主机的操作系统,资源占用少,启动速度快。
-
三、Docker的常用命令
3.1 帮助命令
-
docker --help
:查看所有可用命令。
3.2 镜像命令
-
docker images
:列出本地镜像。 -
docker search <镜像名>
:在Docker Hub搜索镜像。 -
docker pull <镜像名>
:拉取镜像。 -
docker rmi <镜像ID>
:删除镜像。
3.3 容器命令
-
docker run <镜像名>
:创建并运行容器。 -
docker ps
:列出正在运行的容器。 -
docker ps -a
:列出所有容器(包括停止的)。 -
docker stop <容器名>
:停止容器。 -
docker start <容器名>
:启动容器。 -
docker rm <容器名>
:删除容器。 -
docker exec -it <容器名> /bin/bash
:进入容器。
3.4 其他命令
-
docker logs <容器名>
:查看容器日志。 -
docker cp <容器名>:<路径> <本地路径>
:从容器复制文件到主机。 -
docker inspect <容器名>
:查看容器详细信息。
四、Docker镜像
4.1 镜像是什么
-
镜像是一个只读的模板,包含应用程序及其依赖。
-
镜像由多层文件系统组成,每层代表一个文件系统的变更。
4.2 镜像加速原理
-
UnionFS(联合文件系统):允许多个文件系统(层)叠加在一起,形成一个统一的文件系统视图。
-
Docker 镜像加载原型:镜像的每一层都是只读的,当容器启动时,Docker会在镜像顶部添加一个可写的层,用于存储容器运行时的变更。
4.3 分层理解
-
镜像的分层结构使得镜像共享和复用更加高效。
-
多个容器可以共享同一镜像的底层,减少存储空间。
4.4 commit镜像
-
docker commit <容器名> <新镜像名>
:将容器的更改提交为新的镜像。
五、Docker网络
5.1 网络类型
-
Bridge模式:默认网络,容器通过
docker0
网卡连接到宿主机。 -
Host模式:容器直接使用宿主机的网络栈,没有网络隔离。
-
Overlay模式:用于多宿主机的容器网络通信。
-
None模式:容器没有网络。
5.2 网络命令
-
docker network create <网络名>
:创建自定义网络。 -
docker network ls
:列出所有网络。 -
docker network rm <网络名>
:删除网络。 -
docker network connect <网络名> <容器名>
:将容器连接到网络。 -
docker network disconnect <网络名> <容器名>
:将容器从网络断开。
六、Docker Compose
6.1 作用
-
Docker Compose用于定义和管理多容器应用,通过
docker-compose.yml
文件配置服务、网络和卷。
6.2 常用命令
-
docker-compose up
:创建并启动所有服务。 -
docker-compose down
:停止并删除所有服务、网络和卷。 -
docker-compose ps
:列出所有服务的状态。
七、Docker实际应用案例
7.1 运行Nginx服务
bash复制
docker run -d -p 80:80 --name mynginx nginx
7.2 搭建Redis主从同步集群
bash复制
# 主节点
docker run -d -p 6379:6379 \
-v /app/rd1:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=master \
-e REDIS_PASSWORD=123456 \
--network mynet --name redis01 \
bitnami/redis# 从节点
docker run -d -p 6380:6379 \
-v /app/rd2:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=slave \
-e REDIS_MASTER_HOST=redis01 \
-e REDIS_MASTER_PORT_NUMBER=6379 \
-e REDIS_MASTER_PASSWORD=123456 \
-e REDIS_PASSWORD=123456 \
--network mynet --name redis02 \
bitnami/redis
八、Docker在Java开发中的应用
8.1 部署Java应用
-
将Java应用打包成Docker镜像,便于在不同环境中部署。
-
使用
Dockerfile
定义Java应用的运行环境和启动命令。
8.2 示例:部署Spring Boot应用
dockerfile复制
# 使用官方Java镜像作为基础镜像
FROM openjdk:11-jre-slim# 设置工作目录
WORKDIR /app# 复制应用JAR文件到容器
COPY target/myapp.jar /app/myapp.jar# 暴露应用端口
EXPOSE 8080# 启动应用
CMD ["java", "-jar", "myapp.jar"]
通过以上内容的学习,你可以快速掌握Docker的基础知识和实际应用,为Java开发面试做好准备。
九、Docker在Java开发中的应用
一、基础概念
-
Docker:Docker是一个开源的平台,用于开发、部署和运行应用,可通过容器轻松打包应用及其依赖。
-
容器:容器是一个标准的软件单元,它将代码及其所有依赖打包在一起,使Java应用在几乎任何计算环境中都能快速、可靠地运行。
-
镜像:镜像是一个轻量级、独立、可执行的打包格式,包含了运行应用所需的所有内容,包括Java运行环境、代码、库。
二、Java应用的Docker容器化
2.1 Dockerfile 编写
要容器化一个Java应用,首先需要编写一个 Dockerfile
,它定义了如何构建Docker镜像。以下是一个简单的 Dockerfile
示例,用于Java应用:
dockerfile复制
# 使用OpenJDK基础镜像
FROM openjdk:11-jre-slim# 设置工作目录
WORKDIR /app# 复制应用Jar文件到容器
COPY target/my-java-app.jar /app/my-java-app.jar# 暴露应用端口
EXPOSE 8080# 执行Java应用命令
CMD ["java", "-jar", "/app/my-java-app.jar"]
2.2 构建 Docker 镜像
在 Dockerfile
编写完成后,可以使用Docker命令行来构建镜像:
bash复制
docker build -t my-java-app .
此命令会将当前目录下的 Dockerfile
构建成一个名为 my-java-app
的Docker镜像。
2.3 运行 Docker 容器
构建好镜像后,接下来的步骤是运行容器:
bash复制
docker run -d -p 8080:8080 --name my-running-app my-java-app
该命令通过Docker镜像启动一个容器,并将8080端口映射到主机。
三、常见实践
3.1 使用Multi-stage构建
Multi-stage构建允许我们在一个 Dockerfile
中使用多个 FROM
命令,从而简化镜像并减少最终镜像的体积:
dockerfile复制
# 第一阶段:构建应用
FROM maven:3.8-openjdk-11 as builder
WORKDIR /build
COPY . .
RUN mvn clean package# 第二阶段:创建运行时镜像
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /build/target/my-java-app.jar /app/my-java-app.jar
EXPOSE 8080
CMD ["java", "-jar", "/app/my-java-app.jar"]
3.2 环境变量配置
在容器化应用中,使用环境变量进行配置是一种推荐做法。可以在 Dockerfile
中或在 docker run
命令中设置:
dockerfile复制
ENV APP_ENV=production
运行时覆盖:
bash复制
docker run -e APP_ENV=staging -d -p 8080:8080 my-java-app
3.3 日志管理
为了有效管理日志,建议将Docker容器的日志输出到stdout和stderr,以便使用Docker自带的日志驱动进行管理。
四、最佳实践
4.1 优化镜像体积
-
使用更小的基础镜像,比如
alpine
。 -
清理不必要的构建依赖。
-
使用
.dockerignore
文件忽略不需要添加到镜像中的文件。
4.2 安全性考虑
-
使用非root用户运行应用。
-
定期更新基础镜像以获取安全补丁:
dockerfile复制
# 创建用户并使用
RUN addgroup --system appgroup && adduser --system appuser --ingroup appgroup
USER appuser
4.3 版本管理
-
为不同版本的应用打上不同标签:
my-java-app:1.0.0
。 -
使用CI/CD工具自动化构建和推送镜像。
五、Docker在Java开发中的应用案例
5.1 部署Spring Boot应用
假设我们有一个简单的Spring Boot应用,项目结构如下:
复制
my-spring-boot-app
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── myapp
│ │ │ ├── controller
│ │ │ │ └── HelloController.java
│ │ │ └── MyAppApplication.java
│ │ └── resources
│ │ ├── application.properties
│ │ └── static
│ │ └── index.html
│ └── test
│ └── java
│ └── com
│ └── example
│ └── myapp
│ └── MyAppApplicationTests.java
├── pom.xml
其中HelloController.java代码如下:
java复制
package com.example.myapp.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {@GetMapping("/")public String hello() {return "Hello, Docker with Spring Boot!";}
}
MyAppApplication.java代码如下:
java复制
package com.example.myapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyAppApplication {public static void main(String[] args) {SpringApplication.run(MyAppApplication.class, args);}
}
1、创建 Dockerfile:在项目根目录下创建一个名为Dockerfile的文件,内容如下:
dockerfile复制
FROM openjdk:11
WORKDIR /app
COPY target/my-spring-boot-app-0.0.1-SNAPSHOT.jar /app/app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
2、构建项目:在项目根目录下执行mvn clean package
命令,生成可执行的 JAR 包。 3、构建镜像:在项目根目录下执行以下命令构建镜像:
bash复制
sudo docker build -t my-spring-boot-app .
4、运行容器:构建镜像成功后,就可以运行容器了:
bash复制
sudo docker run -d -p 8080:8080 my-spring-boot-app
5.2 多容器应用(以 Java Web 应用和 MySQL 为例)
1、添加依赖:在pom.xml文件中添加 MyBatis-Plus 和相关依赖:
xml复制
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>最新版本号</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency>
</dependencies>
2、配置文件:在application.properties中添加数据库连接和 MyBatis-Plus 相关配置:
properties复制
spring.datasource.url=jdbc:mysql://mysql:3306/javadb?useSSL=false&characterEncoding=utf8
spring.datasource.username=javauser
spring.datasource.password=javapassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis-plus.mapper-locations=classpath:/mapper/*.xml
mybatis-plus.type-aliases-package=com.example.mywebapp.entity
3、代码实现:
-
User.java实体类:
java复制
package com.example.mywebapp.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("users")
public class User {private Integer id;private String name;
}
-
UserMapper.java接口:
java复制
package com.example.mywebapp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mywebapp.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
-
IUserService.java接口:
java复制
package com.example.mywebapp.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mywebapp.entity.User;
public interface IUserService extends IService<User> {
}
-
UserServiceImpl.java实现类:
java复制
package com.example.mywebapp.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mywebapp.entity.User;
import com.example.mywebapp.mapper.UserMapper;
import com.example.mywebapp.service.IUserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
-
UserController.java控制器:
java复制
package com.example.mywebapp.controller;
import com.example.mywebapp.entity.User;
import com.example.mywebapp.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/user")public User getUser(@RequestParam Integer id) {return userService.getById(id);}
}
-
MyBatisPlusConfig.java配置类(可选,用于自定义 MyBatis-Plus 配置):
java复制
package com.example.mywebapp.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.example.mywebapp.mapper")
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor;}
}
4、创建 Dockerfile:在项目根目录下创建一个名为Dockerfile的文件,内容如下:
dockerfile复制
FROM tomcat:9.0
WORKDIR /usr/local/tomcat/webapps
COPY target/my-java-web-app.war ROOT.war
EXPOSE 8080
CMD ["catalina.sh", "run"]
5、构建项目:在项目根目录下执行mvn clean package
命令,生成可执行的 WAR 包。 6、构建镜像:在项目根目录下执行以下命令构建镜像:
bash复制
sudo docker build -t my-java-web-app .
7、运行容器:构建镜像成功后,就可以运行容器了:
bash复制
sudo docker run -d -p 8081:8080 --link my-mysql:mysql my-java-web-app
参数解释:
-
--link my-mysql:mysql
:将 Java Web 应用容器与 MySQL 容器建立链接,my-mysql
是 MySQL 容器的名称,mysql
是链接别名,方便在 Java Web 应用中通过mysql
来访问 MySQL 容器。 -
-p 8081:8080
:将容器内部的 Tomcat 端口 8080 映射到主机的 8081 端口。
通过浏览器访问 http://localhost:8081/user?id=1
,就可以看到根据数据库查询结果展示的用户信息页面,这两个容器之间通过网络进行通信,协同工作