dockerfile镜像构建和docker compose编排

文章目录


前言

本文聚焦 Docker 镜像构建与 Compose 编排核心技术,从镜像分层原理、Dockerfile 指令,到多镜像实战与 Compose 配置部署,助力读者掌握容器化应用开发与运维全流程。


一、docker镜像的分层结构

镜像分层 :Docker 镜像不是单一文件,而是由多层文件系统组成。每执行一条 Dockerfile 指令,都会生成新的镜像层。容器启动时会在镜像的只读层上添加一层可读写层。
镜像缓存 :Docker 会缓存每一层的镜像,如果某一层的内容没有变化,则会复用缓存层,以提高构建效率。
总结:Docker 镜像分层是 "只读增量堆叠 + 共享未改内容"

二、dockerfile操作常用指令

1)FROM

指定新镜像基于的基础镜像,Dockerfile 的第一条指令必须为 FROM 。

示例:FROM debian:7 → 基于 Debian 7 系统作为镜像的基础

2) MAINTAINER

指定镜像的维护者信息:

示例:Docker 官方已推荐用 LABEL maintainer="xxx@xxx.com" 替代(更灵活)

比如:LABEL maintainer="testuser test@example.com"。

3) RUN

执行命令并将结果提交到镜像中。常用来安装软件包、修改配置等。

示例:RUN apt-get update && apt-get install -y nginx → 更新源并安装 Nginx。

4)ENTRYPOINT

设置容器启动时默认执行的命令:

示例:ENTRYPOINT ["nginx"] → 容器启动必执行 nginx 命令。

5)CMD

容器启动时执行的默认命令。 CMD 指令会被 docker run 命令后指定的命令覆盖。

示例:CMD ["-g", "daemon off;"] → 给 nginx 加默认参数(让 nginx 前台运行);如果执行 docker run 镜像名 -g "daemon on;",就会覆盖这个 CMD 参数。

6) EXPOSE

声明容器内的端口:

示例:EXPOSE 80 443 → 告诉使用者这个容器会用到 80(HTTP)和 443(HTTPS)端口,运行时需手动加 -p 8080:80 映射。

7) ENV

设置环境变量:后续指令(RUN/COPY/ENTRYPOINT 等)可通过 变量名引用,也能在容器运行时使用示例: E N V N G I N X V E R S I O N = 1.12.2 → 后续 R U N 中可用 n g i n x − 变量名 引用,也能在容器运行时使用 示例:ENV NGINX_VERSION=1.12.2 → 后续 RUN 中可用 nginx- 变量名引用,也能在容器运行时使用示例:ENVNGINXVERSION=1.12.2→后续RUN中可用nginx−{NGINX_VERSION}.tar.gz 引用版本号,改版本时只需改 ENV 一行。

8) ADD

将文件或目录从宿主机复制到镜像中,支持从 URL 下载文件,并能自动解压归档文件

示例:

  • ADD nginx.tar.gz /usr/local/ → 把本地压缩包复制到镜像,并自动解压;
  • ADD https://xxx.com/file.txt /tmp/ → 从 URL 下载文件到镜像的 /tmp 目录。

9)COPY

将本地文件或目录复制到镜像中

示例:COPY nginx.conf /etc/nginx/ → 把本地的 nginx 配置文件复制到镜像指定目录

10) VOLUME

在容器中创建挂载点

示例:VOLUME ["/var/log/nginx"] → 容器运行时,/var/log/nginx 目录的数据会持久化到宿主机卷中。

11)USER

设置容器内运行命令时的用户

示例:

  • 先创建用户:RUN useradd -r nginx;
  • 切换用户:USER nginx → 后续命令都以 nginx 普通用户运行(提高安全性)

12)WORKDIR

设置后续指令的工作目录

示例:WORKDIR /tmp → 后续 RUN/COPY/ADD 等指令都在 /tmp 目录下执行,无需写绝对路径。

13)ONBUILD

设置当该镜像作为基础镜像时,后续 Dockerfile 执行的命令

示例:ONBUILD COPY custom.conf /etc/nginx/ → 若有另一个 Dockerfile 基于这个镜像构建,会自动把它本地的 custom.conf 复制到镜像中。

14) HEALTHCHECK

设置容器的健康检查

  • --interval=30s:每 30 秒检查一次;
  • --timeout=5s:检查命令超时时间 5 秒;
  • --retries=3:失败 3 次后标记为不健康。

示例:HEALTHCHECK --interval=30s CMD curl -f http://localhost:80 || exit 1 → 每 30 秒用 curl 访问本地 80 端口,访问失败则返回 1(标记不健康)。

基于指令的完整示例:

复制代码
# 1. FROM:基础镜像(CentOS 7)
FROM centos:7
# 2. MAINTAINER:维护者(新版推荐用 LABEL,这里保留)
MAINTAINER testuser <test@example.com>
# 3. ENV:环境变量(后续指令引用). doker中定义变量
# nginx版本 和 安装路径
ENV NGINX_VERSION=1.12.2 \
    WORK_PATH=/usr/local/nginx
# 4. WORKDIR:设置工作目录(提前创建,避免后续 cd 出错)
# 进入/opt目录,在该目录下下载资源并作后续操作
#RUN/COPY/ADD/ENTRYPOINT 等所有指令,都会以 /tmp 作为 "当前工作目录"。
WORKDIR /opt 
# 5. RUN:安装依赖(修复包管理器+包名,新增curl用于健康检查)
RUN yum install -y gcc make pcre-devel zlib-devel wget curl && \
    # 下载并解压 Nginx 源码
    wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz && \
    tar -zxf nginx-${NGINX_VERSION}.tar.gz && \
    # 编译安装 Nginx
    cd nginx-${NGINX_VERSION} && \
    ./configure --prefix=${WORK_PATH} && \
    make && make install && \
    # 清理临时文件(所有/tmp操作完成后清理)
    yum clean all && rm -rf /tmp/*
# 6. COPY:复制本地配置文件(需确保本地有nginx-default.conf文件)
#「把你本地电脑里的 nginx-default.conf 文件,复制到正在构建的 Docker 镜像里
# 的 ${WORK_PATH}/conf/ 目录下,并重命名为 nginx.conf」。
COPY ./nginx-default.conf ${WORK_PATH}/conf/nginx.conf
# 7. ADD:下载密钥+解压模块(修复/opt路径,清理后重新创建/opt)
# 从指定的 URL 下载 nginx_signing.key 这个密钥文件,直接放到镜像里的 /opt/ 目录下,并重命名为 nginx.key(如果镜像里没有 /opt 目录,ADD 会自动创建)。
# 为什么要下载这个密钥?
#这是 Nginx 官方的签名密钥,后续如果需要验证 Nginx 安装包的合法性(比如防止包被篡改),就可以用这个密钥做校验,是构建镜像时的 "安全操作"。
#和 COPY 的区别:COPY 只能复制本地文件,没法下载网络文件,这是 ADD 独有的功能。
ADD https://nginx.org/keys/nginx_signing.key /opt/nginx.key
#给 Nginx 加装额外模块(比如防盗链、缓存模块),这些模块打包成压缩包后,用 ADD 一键复制 + 解压,直接放到 Nginx 的模块目录里,启动时就能加载。
ADD ./nginx-modules.tar.gz ${WORK_PATH}/modules/
# 8. EXPOSE:声明端口
# 写了 EXPOSE 80 443,不代表容器启动后,宿主机就能访问 80/443 端口!
# 想要宿主机能访问,必须在启动容器时加 -p 参数
# docker run -p 8080:80 -p 4433:443 你的镜像名
#「给人看」:其他开发者拿到你的镜像,看 docker inspect 镜像名 就能看到 EXPOSE 80 443,立刻知道这个容器需要映射 80/443 端口;
EXPOSE 80 443
# 9. VOLUME:创建挂载点(放在文件复制后,避免覆盖)
# 容器里 Nginx 的日志会直接写到 /宿主机/日志目录,
#网页文件也会和 /宿主机/网页目录 同步,删了容器,宿主机里的日志 / 网页还在。
VOLUME ["/var/log/nginx", "${WORK_PATH}/html"]
# 10. USER:创建并切换用户(CentOS 7 需确保/sbin/nologin存在)
RUN useradd -r -s /sbin/nologin nginx
# 从这行开始,Dockerfile 后续所有指令(HEALTHCHECK、ENTRYPOINT、CMD),
#以及容器启动后运行的 Nginx 进程,都会以 nginx 用户的身份执行,而不是默认的 root。
USER nginx
# 11. HEALTHCHECK:健康检查(修复curl依赖,调整参数)
# Docker 会每隔 30 秒检查一次容器里的 Nginx 是否真的在正常工作,单次检查超时 5 秒,连续 3 次失败就标记容器 "不健康",方便你及时发现 Nginx 挂了。
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD curl -f http://localhost:80 || exit 1
# 12. ENTRYPOINT:修复变量引用(用shell格式解析环境变量)
#容器启动时,必须执行的 "主命令" 是「启动 Nginx」,而且要通过 shell 解析环境变量,还能接收后续的参数(比如 CMD 传的参数)。
ENTRYPOINT ["/bin/sh", "-c", "${WORK_PATH}/sbin/nginx $@"]
# 13. CMD:默认参数(前台运行Nginx)
# 给 ENTRYPOINT 里的 Nginx 命令传默认参数,让 Nginx 以 "前台运行" 的方式启动;如果 docker run 时手动加参数,会替换掉这个默认参数。
CMD ["-g", "daemon off;"]
# 14. ONBUILD:触发器(最后声明)
# 当其他 Dockerfile 把这个镜像当作基础镜像时,才会自动执行这个指令。
# 把「引用者 Dockerfile 同目录下的 custom.conf」复制到镜像的 Nginx 子配置目录
ONBUILD COPY ./custom.conf ${WORK_PATH}/conf/conf.d/
# 15.构建镜像
docker build -t my-web-server .

三、dockerfile构建镜像实战

1、构建SSH镜像

mkdir /opt/sshd

cd /opt/sshd

一定要将yum源文件和Dockerfile 文件放在同一个目录下

cp /etc/yum.repos.d/CentOS-Base.repo ./

vim Dockerfile

复制代码
#1第一行必须指明基于的基础镜像
FROM centos:7
#2作者信息 MAINTAINER 维护者名称 <维护者邮箱>
MAINTAINER sjj <sjj@example.com>
#3复制本地文件到容器中
ADD CentOS-Base.repo /etc/yum.repos.d/
#4镜像的操作指令
#清理 yum 缓存,因为默认镜像可能有旧的缓存,清理后避免干扰后续操作
RUN yum clean all
#生成新的 yum 缓存,加快后续 yum install 的速度,不用每次安装都重新下载元数据。
RUN yum makecache
RUN yum -y install openssh* net-tools lsof telnet passwd
RUN echo '123456' | passwd --stdin root
#不使用PAM认证
# PAM 是认证模块,关闭它可以避免一些 SSH 登录的权限问题(比如容器内 PAM 配置不全导致登录失败)。
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config	
#取消pam限制
# 注释掉 pam.d/sshd 里的 session required pam_loginuid.so 这一行,pam_loginuid.so 会检查登录用户的 UID,
# 容器内运行 sshd 时可能因为 UID 映射问题报错,注释掉解决登录问题。
RUN sed -ri '/^session\s+required\s+pam_loginuid.so/ s/^/#/' /etc/pam.d/sshd	
#生成密钥认证文件
#生成 SSH 服务需要的 RSA 等密钥文件,sshd 启动时必须有这些密钥,否则会启动失败,-A 是自动生成所有需要的密钥类型。
RUN ssh-keygen -t rsa -A		
#创建 root 用户的.ssh 目录(存放 SSH 公钥 / 私钥、authorized_keys 等),设置所属用户为 root,权限 700(只有 root 能读写执行),权限不对会导致 SSH 登录时密钥认证失败。
RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh
#5声明端口
#声明容器暴露 22 端口(SSH 默认端口),只是声明,不会自动映射,启动容器时需要 - p 2222:22 这样的参数映射。
EXPOSE 22
#6/usr/sbin/sshd -D 用于前台启动sshd服务
# -D是sshd自带的命令,否则会自动关闭掉
# 让 sshd 在前台运行(站在容器内的视角,就是前台运行。宿主机视角有-d决定)
#启动 sshd 服务,-D 参数是让 sshd 在前台运行(不后台守护),因为 Docker 容器的生命周期和前台进程绑定,后台运行的话容器会秒退
# 例如:启动容器,镜像名后加 /usr/sbin/sshd(覆盖原 CMD)
# docker run -d --name sshd-override sshd:centos /usr/sbin/sshd 这个时候容器会退出,因为主进程执行完退出
CMD ["/usr/sbin/sshd" , "-D"]			

生成镜像

复制代码
# 例如在/opt/sshd/目录下执行的构建语句,就会在这个目录找Dockerfile文件等资源
# Dockerfile 名字不能变,构建多个镜像需要创建好目录,在不同目录下执行构建语句
docker build -t sshd:centos .    # 如果Dockerfile文件某个路径错了,重新执行即可

启动容器并修改root密码

docker run -d -P sshd:centos

docker ps -a

ssh localhost -p 49153 #映射的端口号。 ssh -p 访问本地的端口

2、构建Systemctl镜像

mkdir /opt/systemctl

cd /opt/systemctl

vim Dockerfile

复制代码
FROM sshd:centos
MAINTAINER this is systemctl image <hmj>
#在容器里设个 "环境标记",告诉 systemd:"你现在是在 Docker 容器里跑,
#不是在物理机 / 虚拟机里",让它别瞎启动那些只在物理机里才需要的服务(比如开机自检、硬件驱动相关的),避免启动失败。
ENV container docker
#除了systemd-tmpfiles-setup.service,删除其它所有文件
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \	
rm -f /lib/systemd/system/multi-user.target.wants/*; \
rm -f /etc/systemd/system/*.wants/*; \
rm -f /lib/systemd/system/local-f.target.wants/*; \
rm -f /lib/systemd/system/sockets.tsarget.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
#启动这个容器的时候,必须把宿主机的cgroup目录,挂到容器的/sys/fs/cgroup这个位置来",不然 systemctl 没工具用,直接罢工。
#只用需要的服务
VOLUME [ "/sys/fs/cgroup" ]
#CMD ["/usr/sbin/init"]

生成镜像

docker build -t systemd:centos .

启动容器,并挂载宿主机目录挂载到容器中,和进行初始化

#--privileged:使container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。

docker run --privileged -d -P -v /sys/fs/cgroup:/sys/fs/cgroup:ro systemd:centos /sbin/init

docker ps -a

//进入容器

docker exec -it a1ea25ff5ace bash

systemctl status sshd

3、构建nginx镜像

mkdir /opt/nginx

cd /opt/nginx/

cp /opt/nginx-1.20.2.tar.gz /opt/nginx

vim Dockerfile

复制代码
#基于基础镜像
FROM centos:7
#用户信息
MAINTAINER this is nginx image <sjj@qq.com>
ADD CentOS-Base.repo /etc/yum.repos.d/
RUN yum clean all
RUN yum makecache
#添加环境包
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make
RUN useradd -M -s /sbin/nologin nginx
#上传nginx软件压缩包,并解压
ADD nginx-1.20.2.tar.gz /opt/
#指定工作目录
WORKDIR /opt/nginx-1.20.2
RUN ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_stub_status_module && make && make install
#设置环境变量,$PATH保留容器系统原来的PATH
ENV PATH /usr/local/nginx/sbin:$PATH
#指定http和https端口
EXPOSE 80
EXPOSE 443
RUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf			#关闭 nginx 在后台运行
# CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"] (会报错)
CMD ["/usr/local/nginx/sbin/nginx"]

//创建新镜像

docker build -t nginx:centos .

docker run -d -P nginx:centos

4、构建tomcat镜像

mkdir /opt/tomcat

cd /opt/tomcat

cp /opt/jdk-8u91-linux-x64.tar.gz /opt/tomcat

cp /opt/apache-tomcat-8.5.16.tar.gz /opt/tomcat

vim Dockerfile

复制代码
FROM centos:7
MAINTAINER this is tomcat image <hmj>
ADD jdk-8u91-linux-x64.tar.gz /usr/local/
WORKDIR /usr/local/
RUN mv jdk1.8.0_91 /usr/local/java
ENV JAVA_HOME /usr/local/java
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH $JAVA_HOME/bin:$PATH
ADD apache-tomcat-8.5.16.tar.gz /usr/local/
WORKDIR /usr/local/
RUN mv apache-tomcat-8.5.16 /usr/local/tomcat
EXPOSE 8080
#CMD ["/usr/local/tomcat/bin/catalina.sh","run"]
#  catalina.sh run 是 Tomcat 专门的前台运行模式 开启前台运行模式
#  ENTRYPOINT 不会被覆盖
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]
CMD ["/usr/local/tomcat/bin/startup.sh","start"]

//创建新镜像

docker build -t tomcat:centos .

docker run -d --name tomcat01 -p 1216:8080 tomcat:centos

5、构建mysql镜像

mkdir /opt/mysqld

cd /opt/mysqld

vim Dockerfile

复制代码
FROM centos:7
MAINTAINER sjj <sjj@qq.com>
RUN yum -y install ncurses ncurses-devel bison cmake pcre-devel zlib-devel gcc gcc-c++ make
RUN useradd -M -s /sbin/nologin mysql
ADD boost_1_59_0.tar.gz /usr/local/src/
ADD mysql-5.7.17.tar.gz /usr/local/src/
RUN mv /usr/local/src/boost_1_59_0 /usr/local/boost 
WORKDIR /usr/local/src/mysql-5.7.17/
RUN cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DSYSCONFDIR=/etc \
-DSYSTEMD_PID_DIR=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8  \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DWITH_BOOST=/usr/local/boost \
-DWITH_SYSTEMD=1;make -j4;make install
ADD my.cnf /etc/my.cnf
EXPOSE 3306
RUN chown -R mysql:mysql /usr/local/mysql/;chown mysql:mysql /etc/my.cnf
WORKDIR /usr/local/mysql/bin/
RUN ./mysqld \
--initialize-insecure \
--user=mysql \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data;cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/;systemctl enable mysqld
ENV PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH
VOLUME [ "/usr/local/mysql" ]
CMD ["/usr/sbin/init"]

vim my.cnf

复制代码
[client]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock
[mysql]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock
[mysqld]
user = mysql
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
character_set_server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
server-id = 1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES

创建新镜像

docker build -t mysql:centos .

启动容器,并进行初始化

docker run --name=mysql_server -d -P --privileged mysql:centos

进入容器,授权远程连接 mysql

docker exec -it mysql_server /bin/bash

复制代码
mysql -u root -p
grant all privileges on *.* to 'root'@'%' identified by '123456';
grant all privileges on *.* to 'root'@'localhost' identified by '123456';
flush privileges;

在客户端连接mysql容器

本文在windows上通过Navicat连接容器mysql

四、Docker Compose 编排

1、概述

Docker-Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。

Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器

(container)。Docker-Compose运行目录下的所有文件(docker-compose.yml,extends文件或环

境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖。一个服务当中可包括多个容器实例,Docker-Compose并没有解决负载均衡的问题,因此需要借助其它工具实现服务发现及负载均衡,比如Consul。

Docker-Compose的工程配置文件默认为docker-compose.yml,可通过环境变量COMPOSE_FILE或-f参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。

2、 Docker Compose 环境安装

复制代码
# cd /opt  直接拖动docker-compose-v2.24文件,直接赋权使用
mv docker-compose-v2.24.3 /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
#查看版本
docker-compose --version

3、YMAL文件格式

  • 大小写敏感:YAML 是大小写敏感的,所以一定要注意区分大小写。
  • 缩进:YAML 使用空格进行缩进,不支持 TAB 缩进。通常推荐使用两个空格作为一个层级的缩
    进。
  • 列表:列表项使用 - (短横线)表示。
  • 字典:字典使用 : (冒号)连接键值对,冒号后面需要加一个空格。
  • 注释:使用 # 来添加注释。
  • 字符串:如果字符串包含特殊字符,可以使用单引号 ' 或双引号 " 来包裹。

4、Docker Compose配置常用字段

复制代码
build					指定 Dockerfile 文件名
dockerfile 			构建镜像上下文路径
context 				可以是 dockerfile 的路径,或者是指向 git 仓库的 url 地址
image 				指定镜像
command: 			执行命令,覆盖容器启动后默认执行的命令
container_name 	指定容器名称,由于容器名称是唯一的,如果指定自定义名称,则无法scale指定容器数量
deploy 				指定部署和运行服务相关配置,只能在 Swarm 模式使用
environment 		添加环境变量
networks 			加入网络,引用顶级networks下条目
network_mode 	设置容器的网络模式,如 host,bridge,...
ports				     暴露容器端口,与 -p 相同,但端口不能低于 60
volumes 			挂载一个宿主机目录或命令卷到容器,命名卷要在顶级
volumes 			定义卷名称
volumes_from 	从另一个服务或容器挂载卷,可选参数 :ro 和 :rw,仅版本 '2' 支持
hostname 			容器主机名
sysctls 				在容器内设置内核参数
links 					连接到另外一个容器,- 服务名称[:服务别名]
privileged 			用来给容器root权限,注意是不安全的,true | false
restart 				设置重启策略,no,always,nounless-st-failure,oped
						no 默认策略,在容器退出时不重启容器。
						on-failure  在容器非正常退出时(退出状态非0),才会重启容器。
						on-failure:3,在容器非正常退出时重启容器,最多重启3次。
always                在容器退出时总是重启容器。
unless-stopped   在容器退出的容器时总是重启容器,但是不考虑在 Docker 守护进程启动时就已经停止了。
depends_on        
在使用Compose时,最大的好处就是少打启动命令,但一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,可能会因为容器依赖问题而启动失败。例如在没启动数据库容器的时候启动应用容器,应用容器
会因为找不到数据库而退出。depends_on标签用于解决容器的依赖、启动先后的问题。
php:
  depends_on:
    - apache
    - mysql

5、Docker Compose 常用命令

复制代码
字段 											描述
build 											重新构建服务
ps 											列出容器
up 											创建和启动容器
exec 											在容器里面执行命令
scale 										指定一个服务容器启动数量
top 											显示容器进程
logs 											查看容器输出
down 										删除容器、网络、数据卷和镜像
stop/start/restart 							停止/启动/重启服务

6、Docker Compose 文件结构

复制代码
/opt/compose_nginx_tomcat/
├── docker-compose.yml # Docker Compose 配置文件
├── nginx
│ ├── Dockerfile # Nginx 镜像的 Dockerfile
│ └── nginx.conf # Nginx 配置文件
├── tomcat
│ ├── Dockerfile # Tomcat 镜像的 Dockerfile
│ └── webapps
│ └── ROOT.war # Tomcat 应用的 WAR 包
└── wwwroot
└── index.html # 静态文件,Nginx 显示的页面

五、Docker Compose 编写实战

准备nginx镜像构建资源和tomcat构建资源。(上方成功构建的镜像)

配置yml文件

复制代码
version: '3'
services:
  nginx:
    container_name: web1
    hostname: nginx
    build:
      context: ./nginx
      dockerfile: Dockerfile
    ports:
      - 1218:80
      - 1217:443
    networks:
      lnmp:
        ipv4_address: 172.18.0.10
    volumes:
      - ./wwwroot:/usr/local/nginx/html
      - ./nginxconf/nginx.conf:/usr/local/nginx/conf/nginx.conf

  tomcat:
    container_name: tomcat
    build:
      context: ./tomcat
    ports:
      - "1808:8080" # 将宿主机的8080端口映射到Tomcat的8080端口
    networks:
      - lnmp

networks:
  lnmp:
    driver: bridge
    ipam:
      config:
        - subnet: 172.18.0.0/16

将字写入前端资源

echo "123" > wwwroot/index.html

这样就可以访问了,这里触发了反向代理


总结

本文系统讲解 Docker 镜像构建关键技能与 Compose 编排方法,通过多类镜像实战与 Compose 配置演练,帮助读者夯实容器技术基础,提升实际项目部署效率。

相关推荐
计算机小手2 小时前
一个带Web UI管理的轻量级高性能OpenAI模型代理网关,支持Docker快速部署
经验分享·docker·语言模型·开源软件
坚持学习前端日记2 小时前
常见docker指令
docker·容器·eureka
小芳矶3 小时前
Dify本地docker部署踩坑记录
python·docker·容器
70asunflower3 小时前
阿里云无影云电脑 Docker 使用完全指南
阿里云·docker·云计算
久绊A5 小时前
春节前云平台运维深度巡检-实操经验
运维·安全·容器·kubernetes·云平台
feasibility.5 小时前
在OpenCode使用skills搭建基于LLM的dify工作流
人工智能·低代码·docker·ollama·skills·opencode·智能体/工作流
!chen6 小时前
银河麒麟v11 kubeadm部署k8s v1.35.0高可用集群
云原生·容器·kubernetes
DB!!!6 小时前
自学Kubernestes(k8s)Day1 -- 核心基础概念
云原生·容器·kubernetes
lpruoyu6 小时前
【Docker进阶-02】Docker命令
docker·容器
FLGB8 小时前
Docker网段和服务器内部网段172.17 网段冲突导致网络不通
服务器·网络·docker