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 小时前
ubuntu中使用使用Docker-Compose管理MySQL、Apache、PHP容器
mysql·ubuntu·docker·php·apache
峰顶听歌的鲸鱼2 小时前
19.docker 图形化管理界面
运维·笔记·docker·容器·学习方法
好奇的菜鸟2 小时前
Windows 环境下使用 Docker 部署 Java 开发中间件完全指南
java·windows·docker
weixin_46683 小时前
K8S- Calico
云原生·容器·kubernetes
熙客3 小时前
阿里云流水线Docker方式部署操作实战(ACR+流水线)
阿里云·docker·云计算
忍冬行者3 小时前
k8s集群容器创建报failed to write 10087 to cgroup.procs处理
云原生·容器·kubernetes
Hui Baby3 小时前
海豹云创建K8S集群
云原生·容器·kubernetes
JiayinX3 小时前
CI/CD流程搭建【Docker+jenkins+gitlab+Webhook】01
ci/cd·docker·gitlab·jenkins·webhook
xujiangyan_3 小时前
k8s中的pod管理及其优化
linux·容器·kubernetes