Docker 是个划时代的开源项目,它彻底释放了计算虚拟化的威力,极大提高了应用的维护效率,降低了云计算应用开发的成本!使用 Docker,可以让应用的部署、测试和分发都变得前所未有的高效和轻松!

安装

官网安装

step1:运行以下命令卸载所有冲突的包:

for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done

step2:设置Docker的“apt”存储库

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

step3:要安装最新版本,请运行:

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

step3:通过运行“hello-world” 镜像验证安装是否成功:

sudo docker run hello-world

注意事项

在国内使用docker无法使用官方镜像仓库,需要使用镜像加速,如果在阿里云的服务器上使用 Docker,您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://1y6by8x7.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

或者直接使用

sudo docker pull 1y6by8x7.mirror.aliyuncs.com/library/nginx:latest

命令拉取镜像,在其他环境则需要使用公共镜像仓库。

卸载

删除安装包:

sudo apt-get purge docker-ce

删除镜像、容器、配置文件等内容:

sudo rm -rf /var/lib/docker

流转图

仓库

镜像

容器

数据卷

网络

Dockerfile

案例

#
# 抖音关注:程序员三丙
# 知识星球:https://t.zsxq.com/j9b21
#

FROM registry.cn-hangzhou.aliyuncs.com/sanbing/jcpp-base:latest AS base
WORKDIR /app
COPY . .
RUN mvn -U -B -T 0.8C clean install -DskipTests

#分层
FROM registry.cn-hangzhou.aliyuncs.com/sanbing/openjdk:21-jdk-slim-bullseye AS builder
WORKDIR /app
COPY --from=base /app/jcpp-app-bootstrap/target/application.jar application.jar
RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted

# 执行
FROM registry.cn-hangzhou.aliyuncs.com/sanbing/openjdk:21-jdk-slim-bullseye
RUN useradd -m sanbing
WORKDIR /home/sanbing

COPY --from=builder /app/extracted/dependencies/ ./
COPY --from=builder /app/extracted/spring-boot-loader/ ./
COPY --from=builder /app/extracted/snapshot-dependencies/ ./
COPY --from=builder /app/extracted/application/ ./
COPY --from=base /app/jcpp-app-bootstrap/target/conf ./config
COPY --from=base /app/docker/start.sh .

RUN chmod a+x start.sh && \
    mkdir -p /home/sanbing/logs/jcpp &&  \
    mkdir -p /home/sanbing/logs/accesslog &&  \
    mkdir -p /home/sanbing/logs/gc &&  \
    mkdir -p /home/sanbing/logs/heapdump &&  \
    chmod 700 -R /home/sanbing/logs/* &&  \
    chown -R sanbing:sanbing /home/sanbing

EXPOSE 8080 8080

ENV APP_LOG_LEVEL=INFO
ENV PROTOCOLS_LOG_LEVEL=INFO

USER sanbing
CMD ["/bin/bash", "start.sh"]

解释

这段 Dockerfile 是一个多阶段构建的配置,主要用于构建和运行一个基于 Spring Boot 的 Java 应用。以下是逐段解释:

1. 第一阶段:基础镜像(base)

FROM registry.cn-hangzhou.aliyuncs.com/sanbing/jcpp-base:latest AS base
WORKDIR /app
COPY . .
RUN mvn -U -B -T 0.8C clean install -DskipTests

功能:

  • 使用 jcpp-base 作为基础镜像,这里可能包含构建 Java 项目所需的环境(如 Maven)。

  • 设置工作目录为 /app。

  • 将当前项目代码复制到镜像的 /app 目录。

  • 使用 Maven 构建项目,跳过测试(-DskipTests)。

  • -U:强制更新依赖。

  • -B:以非交互模式运行。

  • -T 0.8C:并行构建,使用 CPU 的 80%。

结果:

  • 构建完成后,生成的 JAR 文件位于 jcpp-app-bootstrap/target/application.jar。

2. 第二阶段:分层优化(builder)

FROM registry.cn-hangzhou.aliyuncs.com/sanbing/openjdk:21-jdk-slim-bullseye AS builder
WORKDIR /app
COPY --from=base /app/jcpp-app-bootstrap/target/application.jar application.jar
RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted

功能:

  • 使用 openjdk 的轻量级镜像作为基础镜像。

  • 将第一阶段生成的 JAR 文件复制到当前阶段。

  • 使用 Spring Boot 的分层工具将 JAR 文件解压为多个逻辑层(dependencies、spring-boot-loader、snapshot-dependencies、application)。

  • --layers:启用分层。

  • --destination extracted:指定解压目录。

结果:

  • JAR 文件被分解为多个层,便于缓存和重用,减少后续镜像构建时间。

3. 第三阶段:运行环境

FROM registry.cn-hangzhou.aliyuncs.com/sanbing/openjdk:21-jdk-slim-bullseye
RUN useradd -m sanbing
WORKDIR /home/sanbing

COPY --from=builder /app/extracted/dependencies/ ./
COPY --from=builder /app/extracted/spring-boot-loader/ ./
COPY --from=builder /app/extracted/snapshot-dependencies/ ./
COPY --from=builder /app/extracted/application/ ./
COPY --from=base /app/jcpp-app-bootstrap/target/conf ./config
COPY --from=base /app/docker/start.sh .

功能:

  • 使用轻量级的 openjdk 镜像作为运行环境。

  • 创建一个名为 sanbing 的用户,用于运行容器,增强安全性。

  • 设置工作目录为 /home/sanbing。

  • 从第二阶段复制分层解压的内容到当前镜像。

  • 从第一阶段复制配置文件和启动脚本。

4. 配置与权限

RUN chmod a+x start.sh && \
    mkdir -p /home/sanbing/logs/jcpp &&  \
    mkdir -p /home/sanbing/logs/accesslog &&  \
    mkdir -p /home/sanbing/logs/gc &&  \
    mkdir -p /home/sanbing/logs/heapdump &&  \
    chmod 700 -R /home/sanbing/logs/* &&  \
    chown -R sanbing:sanbing /home/sanbing

功能:

  • 为启动脚本 start.sh 添加执行权限。

  • 创建日志目录:

  • jcpp:可能是主应用日志。

  • accesslog:访问日志。

  • gc:垃圾回收日志。

  • heapdump:堆转储文件。

  • 设置日志目录权限为 700(仅拥有者可访问)。

  • 更改所有权为用户 sanbing。

5. 暴露端口

EXPOSE 8080 8080

功能:

  • 暴露容器的 8080 端口,用于接收外部请求。

6. 环境变量

ENV APP_LOG_LEVEL=INFO
ENV PROTOCOLS_LOG_LEVEL=INFO

功能:

  • 设置默认的日志级别为 INFO。

7. 用户与启动命令

USER sanbing
CMD ["/bin/bash", "start.sh"]

功能:

  • 切换到非 root 用户 sanbing。

  • 指定容器启动时运行的命令为 start.sh。

Java 实战

使用 jar 包

使用 Docker 运行自己编写的 Java 程序,可以通过以下步骤完成:

step 1. 准备 Java 程序

确保你已经编写并打包了一个 Java 程序(例如,HelloWorld.java)。如果没有打包,可以先创建一个简单的 Java 程序:HelloWorld.java

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Docker!");
    }
}

编译程序,生成 .class 文件:

javac HelloWorld.java

如果需要生成可执行 JAR 文件,可以使用以下命令:

jar cvfe HelloWorld.jar HelloWorld HelloWorld.class

step 2. 创建 Dockerfile

创建一个名为 Dockerfile 的文件,用于定义构建镜像的步骤。

示例 Dockerfile

# 使用官方的 OpenJDK 镜像作为基础镜像
FROM openjdk:17-jdk-slim

# 将 JAR 文件复制到容器中
COPY HelloWorld.jar /app/HelloWorld.jar

# 设置工作目录
WORKDIR /app

# 定义运行容器时的默认命令
CMD ["java", "-jar", "HelloWorld.jar"]

step 3. 构建 Docker 镜像

在包含 Dockerfile 和 HelloWorld.jar 的目录中运行以下命令:

docker build -t my-java-app .

构建成功后,可以通过以下命令查看镜像:

docker images

step 4. 运行 Docker 容器

运行容器:

docker run --rm my-java-app

输出应为:

Hello, Docker!

step 5. 验证和调试

如果程序需要接受输入或参数,可以通过以下方式运行:

docker run --rm my-java-app arg1 arg2

需要修改 Dockerfile 的 CMD 为:

CMD ["java", "-jar", "HelloWorld.jar"]

如果需要调试,可以进入容器内部:

docker run -it --rm my-java-app /bin/bash

step 6. 发布到 Docker Hub(可选)

如果需要分享你的镜像,可以将其推送到 Docker Hub:

docker tag my-java-app your-dockerhub-username/my-java-app
docker push your-dockerhub-username/my-java-app

之后,其他人可以通过以下命令拉取并运行:

docker run --rm your-dockerhub-username/my-java-app

完整项目结构

project/
├── Dockerfile
├── HelloWorld.java
└── HelloWorld.jar

使用 git

Docker 可以直接从 Git 仓库构建镜像,而无需先将代码克隆到本地。以下是具体操作步骤:

step 1. 准备 Git 仓库

确保 Git 仓库中包含一个有效的 Dockerfile,用于定义如何构建镜像。

示例 Git 仓库结构

repository/
├── Dockerfile
├── src/
│  └── Main.java
├── pom.xml
└── README.md

step 2. 使用 Docker 从 Git 仓库构建镜像

直接运行以下命令,从远程 Git 仓库构建镜像:

docker build -t my-java-app https://github.com/username/repository.git
  • -t my-java-app:指定镜像的名称。
  • https://github.com/username/repository.git:Git 仓库地址。

Docker 会自动从指定的 Git 仓库拉取代码并根据 Dockerfile 构建镜像。

step 3. 运行构建的镜像

构建完成后,可以运行容器:

docker run --rm my-java-app

step 4. 如果需要指定分支或路径

可以通过 # 指定分支或特定路径:

docker build -t my-java-app https://github.com/username/repository.git#branch-name

或者指定子目录(如果 Dockerfile 不在仓库根目录):

docker build -t my-java-app https://github.com/username/repository.git#:subdir

step 5. 示例 Dockerfile

以下是一个用于构建 Java 应用的 Dockerfile 示例:

# 使用官方 OpenJDK 镜像作为基础镜像
FROM openjdk:17-jdk-slim

# 复制项目文件到容器中
COPY . /app

# 设置工作目录
WORKDIR /app

# 构建项目(适用于 Maven 项目)
RUN ./mvnw clean package

# 运行生成的 JAR 文件
CMD ["java", "-jar", "target/app.jar"]

step 6. 注意事项

  1. 网络访问:确保 Docker 容器可以访问 Git 仓库(例如私有仓库需要配置 SSH 密钥或访问令牌)。
  2. 依赖环境:确保 Dockerfile 定义了项目的构建和运行环境(如 JDK、Maven 等)。
  3. 缓存:Docker 会缓存构建步骤,后续构建速度会更快。