简介

Docker是一种容器化平台,用于在虚拟化的操作系统上创建、部署和运行应用程序。通过Docker,开发人员可以打包应用程序及其依赖项,并在容器中运行它们,从而实现了应用程序的可移植性和可重复性。

Docker容器提供了一种轻量级的虚拟化方式,每个容器都是一个独立的运行环境,拥有自己的文件系统、网络和进程空间。这使得Docker容器可以更快地启动和停止,并且需要更少的资源来运行。

使用Docker,开发人员可以构建、测试和部署应用程序,同时保持环境的一致性。这使得Docker成为一个流行的解决方案,用于构建和运行现代化的分布式应用程序。

一些外链:

三大概念

Docker 包括三个基本概念:

  • 镜像(Image)

  • 容器(Container)

  • 仓库(Repository)

它们之间的关系分别是: 仓库保存镜像、容器启动镜像、镜像保存环境

镜像(Image)

在Docker中,镜像是一种轻量级、可移植的打包方式,用于打包应用程序及其所有依赖项,包括操作系统、库文件和其他必要的组件。镜像可以用来创建Docker容器,从而在容器中运行应用程序。

Docker镜像是只读的,一旦创建就不能更改。镜像是通过Dockerfile定义的,Dockerfile是一个文本文件,其中包含了用于构建镜像的指令和配置信息。通过Dockerfile,开发人员可以指定基础镜像、安装软件包、设置环境变量和运行命令等操作,最终生成一个新的镜像。

Docker镜像是通过Docker Hub或其他Docker仓库进行共享和分发的。Docker Hub是一个公共的Docker镜像仓库,其中包含了大量的镜像,用户可以从中获取所需的镜像,也可以将自己创建的镜像上传到Docker Hub上进行共享。同时,也可以在私有的Docker仓库中存储和管理自己的镜像,以便在内部使用或私下共享。

Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。

容器(Container)

在Docker中,容器是一个独立的运行环境,包含了应用程序及其依赖项,可以在任何支持Docker的平台上运行。Docker容器是基于Docker镜像创建的,每个容器都是一个相互隔离的运行环境,拥有自己的文件系统、网络和进程空间,与主机操作系统和其他容器完全隔离。

容器是轻量级的,启动速度快,所需的资源也较少。使用Docker,开发人员可以快速地创建、启动和停止容器,并在容器中运行应用程序,从而实现了应用程序的可移植性和可重复性。

Docker容器可以通过Docker命令行工具进行管理,例如启动、停止、重启、删除等操作。同时,Docker还提供了一系列的命令行工具和API,可以对容器进行监控、调试和管理。

使用Docker容器,开发人员可以更轻松地构建和部署现代化的分布式应用程序,从而实现了应用程序的可移植性和可重复性。

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

仓库(Repository)

在Docker中,仓库是用于存储和管理Docker镜像的中心化服务。Docker仓库是一个中央集中的存储库,用于存储和管理Docker镜像,同时还提供了镜像的标签和元数据等信息。

Docker Hub是最流行的公共Docker仓库,其中包含了数以万计的Docker镜像,开发人员可以从Docker Hub获取所需的镜像。同时,Docker Hub也是一个社区,用户可以将自己的镜像上传到Docker Hub上进行共享和分发。

除了Docker Hub外,Docker还支持私有Docker仓库,开发人员可以在内部搭建私有的Docker仓库,用于存储和管理自己的Docker镜像。私有Docker仓库可以提供更高的安全性和可控性,同时也可以加速应用程序的构建和部署过程。

Docker仓库可以通过Docker命令行工具进行管理,例如搜索、拉取、推送和删除镜像等操作。同时,Docker还提供了一些工具和API,用于管理和监控Docker仓库的状态和性能。

仓库可看成一个代码控制中心,用来保存镜像。

安装

Windows

官方安装网址:Docker Desktop release notes | Docker Docs

下载后按提示安装即可,注意需要将windows中的hyper-V打开(若没打开,docker的安装程序会自动打开)

Ubuntu

更新apt包索引

sudo apt update

安装一些必要的软件包,这些软件包允许apt通过HTTPS使用仓库

sudo apt install -y apt-transport-https ca-certificates curl software-properties-common

添加Docker的官方GPG密钥

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

添加Docker仓库到apt源中。在终端中输入以下命令(注意:这里的$(lsb_release -cs)会自动获取你的Ubuntu版本信息)

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

再次更新apt包索引

sudo apt update

安装Docker

sudo apt install docker-ce docker-ce-cli containerd.io

安装完成后,启动并加入开机启动Docker

sudo systemctl start docker  
sudo systemctl enable docker

验证docker是否安装成功

docker -v

如果需要安装docker compose,则可以使用如下命令进行安装:

sudo apt install docker-compose

HelloWorld

为了更加好得理解docker,这里用docker的一个小案例来帮助读者更快速入门docker。这里就用ubuntu的docker镜像来作为案例。

搜索镜像

首先我们需要搜索仓库中的镜像,使用docker search ubuntu来搜索有关ubuntu的镜像。结果如下:

NAME                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
ubuntu                           Ubuntu is a Debian-based Linux operating sys…   15791     [OK]       
websphere-liberty                WebSphere Liberty multi-architecture images …   293       [OK]       
ubuntu-upstart                   DEPRECATED, as is Upstart (find other proces…   112       [OK]       
neurodebian                      NeuroDebian provides neuroscience research s…   99        [OK]       
ubuntu/nginx                     Nginx, a high-performance reverse proxy & we…   84                   
open-liberty                     Open Liberty multi-architecture images based…   59        [OK]       
ubuntu/apache2                   Apache, a secure & extensible open-source HT…   57                   
ubuntu/squid                     Squid is a caching proxy for the Web. Long-t…   54                   
ubuntu-debootstrap               DEPRECATED; use "ubuntu" instead                50        [OK]       
ubuntu/bind9                     BIND 9 is a very flexible, full-featured DNS…   49                   
ubuntu/mysql                     MySQL open source fast, stable, multi-thread…   44                   
ubuntu/prometheus                Prometheus is a systems and service monitori…   40                   
ubuntu/kafka                     Apache Kafka, a distributed event streaming …   28                   
ubuntu/postgres                  PostgreSQL is an open source object-relation…   27                   
ubuntu/redis                     Redis, an open source key-value store. Long-…   17                   
ubuntu/grafana                   Grafana, a feature rich metrics dashboard & …   9                    
ubuntu/prometheus-alertmanager   Alertmanager handles client alerts from Prom…   8                    
ubuntu/dotnet-deps               Chiselled Ubuntu for self-contained .NET & A…   7                    
ubuntu/zookeeper                 ZooKeeper maintains configuration informatio…   5                    
ubuntu/memcached                 Memcached, in-memory keyvalue store for smal…   5                    
ubuntu/dotnet-runtime            Chiselled Ubuntu runtime image for .NET apps…   5                    
ubuntu/dotnet-aspnet             Chiselled Ubuntu runtime image for ASP.NET a…   4                    
ubuntu/telegraf                  Telegraf collects, processes, aggregates & w…   4                    
ubuntu/cortex                    Cortex provides storage for Prometheus. Long…   3                    
ubuntu/cassandra                 Cassandra, an open source NoSQL distributed …   2                    

这里我们选择ubuntu作为我们的镜像(15791个stars,第一个)

下载镜像

使用如下命令从仓库拉取镜像

docker pull ubuntu

完成后,可以使用docker images查看本地镜像,查看到下载的镜像为成功

REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       latest    08d22c0ceb15   3 weeks ago   77.8MB

创建容器

为了启动镜像,我们需要创建一个容器。使用如下命令创建一个容器

docker run -i -t -d --name hello ubuntu

这个命令为,创建一个可对话(伪终端)、后台持续部署的容器,并命名为hello。其中ubuntu为刚刚pull下来的镜像

使用docker ps -a查看所有容器的状态

CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS              PORTS     NAMES
428b0a1935fb   ubuntu    "/bin/bash"   About a minute ago   Up About a minute             hello

这里可以看到在不到一分钟前已经启动了容器,若docker有很多容器,可以使用docker ps查看启动容器的当前状态

操作容器

我们开启了伪终端的功能,那么我们可以进入该容器,以终端的形式操作这个容器。

docker exec -it hello /bin/bash

后面的/bin/bashdocker ps命令中COMMAND列可看到。进入容器终端后,可以看到:

root@428b0a1935fb:/#

@后面的数字就是容器的ID。之后就可以随意操作了。如果想退出容器,输入exit命令即可。

停止并启动容器

我们结束容器的操作后,可以停止容器启动。使用如下命令停止容器:

docker stop hello

如果想开启,则输入docker start hello开启容器。并且用docker ps查看容器的开启状态

删除容器与镜像

如果不需要容器了,可以删除容器。使用如下命令删除容器:

docker rm -f hello

如果镜像也不需要了,可以删除镜像。使用如下命令删除镜像:

docker rmi ubuntu

使用docker ps -adocker images查看是否删除成功

镜像操作

在Docker中,可以使用命令行工具或者图形用户界面来管理和操作镜像。

搜索镜像

可以使用docker search命令搜索Docker Hub上的镜像。例如:

docker search nginx

拉取镜像

可以使用docker pull命令从Docker仓库中拉取一个镜像。

docker pull ubuntu

查看本地镜像列表

可以使用如下命令查看本地系统中的镜像列表。

docker images

删除镜像

可以使用docker rmi命令删除一个本地系统中的镜像。

docker rmi ubuntu

查看镜像详情

可以使用docker inspect命令查看镜像的详细信息。

docker inspect hello

构建镜像

可以使用Dockerfile来构建一个新的镜像,并使用docker build命令来执行构建。

首先创建一个Dockerfile,其中包含一组指令来告诉 Docker 如何构建我们的镜像。Dockerfile的内容如下:

FROM ubuntu
RUN apt-get update && apt-get install -y nginx

每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。

第一条FROM,指定使用哪个镜像源

RUN 指令告诉docker 在镜像内执行命令,安装了什么。。。

然后执行以下命令来构建镜像:

docker build -t my-nginx-image .
  • -t: 指定要创建的目标镜像名

  • .: Dockerfile文件所在目录,可以指定Dockerfile的绝对路径

容器操作

在Docker中,可以使用命令行工具或者图形用户界面来管理和操作容器。

创建容器

可以使用docker run命令来创建一个新的容器,并在其中运行一个命令或应用程序。以下命令使用 ubuntu 镜像启动一个容器,参数为以命令行模式进入该容器:

docker run -i -t -d --name hello ubuntu /bin/bash

参数说明:

  • -i: 交互式操作。

  • -t: 终端。

  • -d: 后台部署。

  • --name: 指定容器名字。

  • hello: 自定义容器名字。

  • ubuntu: ubuntu 镜像。

  • /bin/bash: 放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

创建完成后,会自动进入容器终端,可以使用exit推出容器终端。

启动容器

可以使用docker start命令来启动一个已经停止的容器。例如:

# 启动容器,hello可以是容器的id和容器名
docker start hello

# 后台启动容器,hello可以是容器的id和容器名
docker start -d hello

停止容器

可以使用docker stop命令来停止正在运行的容器。例如:

docker stop hello

重启容器

可以使用docker restart命令来重启一个正在运行的容器。例如:

docker restart hello

删除容器

可以使用docker rm命令来删除一个已经停止的容器。例如:

docker rm hello

若想强制删除一个容器,可以加-f指令。例如:

docker rm -f hello

查看容器日志

可以使用docker logs命令来查看容器的日志输出。例如:

docker logs hello

# 标准化输出
docker logs -f hello

查看容器启动状态与信息

# 查看正在运行中的容器
docker ps

# 查看本地所有的容器
docker ps -a

进入容器

可以使用docker exec命令在运行的容器中执行命令。

docker exec -it hello /bin/bash

进入容器后,如果想退出容器,则使用exit退出。docker exec命令在退出容器后不会停止容器的运行。

也可以用如下方式进入一个正在运行的容器:

docker attach 容器id

docker exec在进入容器后开启一个新的终端,可以在里面操作。docker attach会进入容器并打开正在执行的终端。

导出容器

可以使用docker export命令将容器导出为一个tar归档文件。例如:

docker export hello > hello.tar

导入容器

在Docker中,可以使用docker import命令将一个tar归档文件导入为一个新的镜像。该镜像是一个新的、不包含任何历史记录或元数据的镜像,因此需要为其指定名称和标签。

以下命令将hello.tar文件导入为一个名为hello的镜像,并为其添加一个标签v1.0:

docker import hello.tar hello/hello:v1.0

查看容器内部进程

可以使用docker top来查看容器内部运行的进程。例如:

docker top hello

查看容器的底层信息

使用docker inspect来查看容器的底层信息。它会返回一个JSON文件记录着Docker容器的配置和状态信息。

docker inspect hello

Web应用容器

我们可以指定端口,创建一个web应用容器

docker run -i -t -d -P --name training_web training/webapp python app.py

-p指令将容器内部使用的网络端口随机映射到我们使用的主机上。也可以指定映射的端口,例如:

docker run -i -t -d -P 8112:80 --name training_web training/webapp python app.py

以上指令将容器内部的8112端口映射到我们本地主机的80端口上。若想访问容器中的web,只需要输入ip:8112即可。

查看Web容器的端口映射

使用docker ps查看容器,可以发现容器信息多了端口信息。

PORTS
0.0.0.0:8112->80/tcp

也可以使用docker port查看容器的端口信息

docker port hello

文件管理

docker类似于虚拟机,假设需要用docker去运行某些代码,我们需要将物理机上的文件传输到docker里面。

docker提供了对应的文件传输命令,那就是cp(copy)指令,cp是基础的指令,可以用于容器和外界物理机之间拷贝文件,命令的主要形式如下:

docker cp 容器ID或名称: 容器文件目录 物理机文件目录

docker cp 物理机文件目录 容器ID或名称: 容器目录

第一条为将容器内的文件复制到物理机上,第二条则是将物理机上的文件复制到容器里

比如想将物理机的/home/user/file目录文件复制到容器ID为a2730e327321/home/file目录下,那么就运行:

docker cp /home/user/file a2730e327321:/home/file/

反过来,我们想将容器ID为a2730e327321/home/file目录下的文件复制到物理机的/home/user/file目录下,那么就运行:

docker cp a2730e327321:/home/file /home/user/file/

注意:

  • 如果源路径是个文件,且目标路径是以/结尾, 则docker会把目标路径当作一个目录,会把源文件拷贝到该目录下(如果不存在则自动创建)。

  • 如果目标文件是个存在的文件,会被源文件覆盖,文件名则为目标文件名。

docker commit

docker commit 是Docker命令行工具中的一个命令,用于将运行中的容器的当前状态保存为一个新的镜像。当你对容器内的文件系统或配置做了更改,并希望将这些更改永久保存下来以供后续使用时,可以使用这个命令。

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
  • OPTIONS:可选参数,例如:

    • -a|--author:指定提交者的姓名和邮箱。

    • -m|--message:提供提交信息(即镜像版本注释)。

    • -p|--pause:在提交之前暂停容器(默认行为,确保提交的是一个稳定的容器状态)。

  • CONTAINER:你要提交的正在运行或已停止的容器的ID或名称。

  • REPOSITORY[:TAG]:新镜像要保存的位置和标签,默认情况下如果没有指定仓库名和标签,则会创建一个没有仓库名、仅包含短ID作为标签的新镜像。

示例:

# 提交名为my_container的容器到本地仓库,并标记为new_image:latest
docker commit -m "Added custom configuration" hello new_image:latest

# 或者只提交容器而不指定仓库和标签,将会生成一个带有随机字符串标签的本地镜像
docker commit hello

# 查看容器提交的镜像
docker images

数据卷

Docker数据卷(Data Volumes)是用于持久化存储容器内数据的机制,它们在容器之间提供了一种持久可共享数据存储方式。Docker容器的数据,可以同步到本地中,若不想容器产生的数据(如数据库的数据)删除后丢失,可以使用数据卷来保证数据的持久性。

数据卷可以将容器内的目录,挂载到本地机上面。为了将容器的数据卷挂载到本地机上,我们可以在 docker run 命令中使用 -v--volume 参数。

docker run -it -d -v 主机目录:容器内目录 镜像ID /bin/bash

除此之外,也可以使用docker volume命令对数据卷进行一系列操作,具体如下:

  • 创建新的数据卷:docker volume create [volume_name]

  • 查看已存在的数据卷:docker volume ls

  • 删除数据卷:docker volume rm [volume_name]

  • 检查数据卷详细信息:docker volume inspect [volume_name]

具名与匿名挂载

匿名挂载是指在创建和使用数据卷时,不为其指定特定名称,而是由Docker自动为数据卷生成一个唯一的、难以预测的哈希值作为其标识。

docker run -v /host/path:/container/path ...

具名挂载则是指在创建数据卷时明确地为其指定一个易于识别的名字,这样可以方便管理和复用该数据卷。

docker run -v named_volume:/container/path ...
或
docker run -v volume_name:/container/path ...

具名挂载提供了更高的可读性和可控性,因为它允许用户通过名称来管理数据卷,而匿名挂载则更为简单快捷,但可能不利于后期维护和追踪。

容器数据卷

数据卷不仅仅可以挂载在本地机上,也可以挂载在容器里。在修改挂载目录下的文件后,容器之间的挂载目录内的文件会自动同步起来。这就实现了容器间的数据共享

使用--volumes-from对目录进行挂载

docker run -it --name docker01 --volumes-from docker02 hello/ubuntu:latest

DockerFile

Dockerfile 是一个文本文件,用于定义如何构建一个新的 Docker 镜像。它是Docker镜像创建过程的蓝图,包含了用户需要运行应用程序及其依赖的所有命令和配置信息。

在Dockerfile中,你可以指定基础镜像、添加文件、设置环境变量、安装软件包、执行自定义脚本等一系列操作。当Docker客户端通过 docker build 命令解析并执行Dockerfile中的指令后,会生成一个新的定制化镜像。

DockerFile命令

Dockerfile中的每个命令都是一层一层的,它有特定的语法和一系列基本指令。这些指令必须全部大写,并且在Dockerfile中按照特定的顺序编写。

Dockerfile的基本指令如下:

FROM:指定制作镜像时依据的基础镜像(这个镜像的妈妈是谁)。

LABEL:用于给镜像添加元数据的指令。元数据以键值对的形式存在,可以用来描述镜像的各种属性,比如版本号、描述信息、维护者信息等。这些信息对于镜像的管理、搜索和分类非常有用。

RUN:在制作镜像时需要执行的命令(你想让它干啥)。

COPY:将文件系统中的文件复制到Docker镜像中,通常用于将应用程序代码或配置文件复制到镜像中。

ADD:将文件系统中的文件复制到Docker镜像中,通常用于将应用程序代码或配置文件复制到镜像中。这个指令类似于COPY指令,但功能更强大,因为它还支持自动解压缩和远程URL获取

WORKDIR:设置工作目录(我是cd,今天化了妆)。

VOLUME:设置容器与外界映射的目录,通常用于数据持久化等操作(给它一个存放行李的地方)。

EXPOSE:设置向外暴露的端口,这样外部可以访问容器内部运行的服务(它要打开的门是啥)。

CMD:指定容器启动时要执行的命令,但只有最后一个CMD会生效。如果Docker容器在启动时被指定了运行的命令,则会覆盖CMD指定的命令。

ENTRYPOINT:指定容器启动时要执行的命令,与CMD不同的是,ENTRYPOINT指定的命令不会被docker run命令中给出的参数覆盖,而是将其作为固定部分一直存在于容器中。如果指定了ENTRYPOINT,则CMD的内容将作为参数传给ENTRYPOINT。

ENV:设置环境变量,这些环境变量可以在后续的指令中使用。

以下是一个简单的Dockerfile示例:

# 指定基础镜像  
FROM alpine:latest  
  
# 设置维护者信息和其他元数据  
LABEL maintainer="Your Name <your.email@example.com>"  
LABEL version="1.0"  
LABEL description="A simple Nginx container based on Alpine Linux with a custom HTML page."  
  
# 设置环境变量  
ENV NGINX_VERSION 1.21.3  
ENV NGINX_HOME /etc/nginx  
  
# 安装Nginx  
RUN apk add --no-cache nginx=${NGINX_VERSION}  
  
# 设置工作目录  
WORKDIR ${NGINX_HOME}  
  
# 将自定义的HTML文件复制到Nginx的默认网页目录下  
COPY index.html /usr/share/nginx/html/  
  
# 暴露80端口  
EXPOSE 80  
  
# 设置容器启动时要执行的命令  
CMD ["nginx", "-g", "daemon off;"]

构建镜像

为了使用这个Dockerfile构建镜像,我们可以使用docker build去构建,docker build 是 Docker 的命令,用于从 Dockerfile 构建一个新的 Docker 镜像。这个命令会根据你提供的 Dockerfile 中的指令,创建一个分层的镜像,该镜像可以作为运行容器的基础。

基本语法如下:

docker build [选项] [--build-arg <参数名>=<值>] [-t <镜像名>:<标签>] [-f <Dockerfile路径>] [<上下文路径或URL>]

各部分含义:

  • --build-arg <参数名>=<值>:用于在构建过程中传递变量给 Dockerfile 中的 ARG 指令。

  • -t <镜像名>:<标签>:指定新镜像的名称和可选标签,默认标签是 "latest",如果不指定标签,则会使用 "latest"。

  • -f <Dockerfile路径>:指定要使用的 Dockerfile 的路径(如果当前目录下没有默认的 Dockerfile 文件)。

  • [<上下文路径或URL>]:这是构建镜像时使用的上下文路径,Docker 将会发送此路径下的所有内容到 Docker daemon 进行构建。如果省略,则默认为当前目录。

例如,一个简单的构建命令如下所示:

docker build -t myimage:v1.0 -f /home/dockerfile

Docker Compose

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。

在没有 Docker Compose 之前,如果你有一个由多个服务(例如:一个 Web 应用、一个数据库、一个缓存服务)组成的项目,你需要:

  1. 为每个服务单独写一个 Dockerfile。

  2. 一个一个地使用 docker build 和 docker run 命令来启动容器,并且要手动设置它们之间的网络连接、数据卷等。

这个过程非常繁琐,且容易出错。

Docker Compose 的出现,让你可以用一个单一的配置文件,来定义整个应用的所有服务、网络、数据卷等。然后,通过一条简单的命令,就能同时启动、停止或重建所有服务。

核心概念与工作流程

  1. 定义环境 (Dockerfile):

  • 首先,你仍然需要为你的应用的每个组件(服务)编写一个Dockerfile,来定义如何构建该服务的镜像。

  1. 定义服务 (docker-compose.yml):

  • 这是 Docker Compose 的核心。你创建一个名docker-compose.yml的 YAML 格式的配置文件。

  • 在这个文件里,你需要定义:

    • 服务:你的应用由哪些容器组成(例如:web 前端服务、db 数据库服务、redis 缓存服务)。

    • 镜像:每个服务使用哪个镜像(可以直接用现成的,如 mysql:8.0,也可以指定 Dockerfile 路径来构建)。

    • 依赖关系:服务之间的启动顺序。

    • 网络:服务之间如何通信。

    • 数据卷:如何挂载宿主机目录到容器,实现数据持久化。

    • 端口映射:将容器端口映射到宿主机端口。

  1. 创建并启动所有的容器 (docker compose up):

  • 在包含 docker-compose.yml 文件的目录下,只需运行一条命令:

docker compose up
  • Docker Compose会:

    • 自动为你创建所需的网络。

    • 根据配置构建或拉取镜像。

    • 按照依赖顺序启动所有容器。

    • 并将所有容器的日志聚合输出到同一个终端窗口。

QuickStart

假设有一个简单的 Python Flask 应用,它使用 Redis 来计数。

项目结构如下:

my-app/
├── app.py
├── requirements.txt
├── Dockerfile
└── docker-compose.yaml

Dockerfile (用于构建 Flask 应用镜像)

FROM python:3.9-alpine
WORKDIR /code
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]

app.py (Flask 应用代码)

python

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379) # 注意这里的host是服务名‘redis’

@app.route('/')
def hello():
    count = cache.incr('hits')
    return f 'Hello World! 该页面已被访问 {count} 次。'

docker-compose.yaml (核心配置文件)

version: '3.8'  # 指定 Compose 文件版本

services:
  web:
    build: .    # 使用当前目录的 Dockerfile 构建镜像
    ports:
      - "8000:5000" # 将宿主机的8000端口映射到容器的5000端口
    depends_on:
      - redis   # 表明 web 服务依赖于 redis 服务

  redis:
    image: "redis:alpine" # 直接使用官方的 Redis 镜像

运行

  • my-app/ 目录下,执行:

    bash

    docker compose up
  • 现在,打开浏览器访问 http://localhost:8000,你就能看到这个应用在运行了。每次刷新,计数都会增加,证明 Flask 应用和 Redis 正在协同工作。

docker-compose.yaml的配置详情

一个典型的 docker-compose.yml 文件主要包含以下部分:

  • version:定义 Compose 文件格式的版本。早期版本(如 3.x)需要此字段,但新版本的 Docker Compose 已逐渐将其设为可选。

  • services:这是文件的核心,你在这里定义所有要运行的容器服务。

  • networks & volumes:在顶层定义自定义的网络和数据卷,以便在多个服务间共享和引用。

下面这个表格汇总了 docker-compose.yml 文件里的核心部分和常用配置指令,方便快速查阅和理解。

分类

配置指令

说明与示例

服务定义

image

指定服务使用的镜像,例如 image: nginx:latest

build

指定通过 Dockerfile 构建镜像的路径。可以简写为路径,例如 build: ./app;也可详细定义上下文和Dockerfile

container_name

为容器指定一个自定义名称,例如 container_name: mysql_db

依赖与启动

depends_on

表达服务间的依赖关系。例如,web 服务可以设置为在 dbredis 服务启动之后才启动

restart

定义容器退出时的重启策略。常用值有 always(总是重启)、on-failure(非正常退出时重启)和 unless-stopped(除非手动停止,否则重启)

网络与端口

ports

映射宿主机端口到容器端口,格式为 "宿主机端口:容器端口",例如 "8080:80"

expose

仅暴露端口给其他服务,而不映射到宿主机,例如 expose: ["3000"]

networks

将服务连接到自定义网络,以实现隔离或分组,例如 networks: - backend

数据持久化

volumes

挂载宿主机目录或数据卷到容器中,用于持久化数据或同步配置文件。例如 - ./app:/usr/src/app(挂载主机目录) 或 - db_data:/var/lib/mysql(使用命名卷)

环境变量

environment

直接以键值对形式设置环境变量,例如 MYSQL_ROOT_PASSWORD: example

env_file

从文件中批量加载环境变量,例如 env_file: .env

其他常用

command

覆盖容器启动后默认执行的命令

这里补充一些表格中指令的常见用法和细节:

  • 构建镜像 (build):除了简单指定路径,你还可以详细定义构建上下文和使用的 Dockerfile 文件。

build:
  context: ./app  # Dockerfile 所在的目录
  dockerfile: Dockerfile.dev  # 指定使用的 Dockerfile 文件名
  • 端口映射 (ports):除了基本的 "宿主机端口:容器端口" 格式,你还可以指定协议(如 "6060:6060/udp"),或仅暴露容器端口让宿主机随机映射(如 "3000")。

  • 数据卷挂载 (volumes)

    • 绑定挂载 (Bind Mount):直接使用宿主机路径,例如 - ./web:/usr/share/nginx/html,常用于开发时同步代码。

    • 命名卷 (Named Volume):使用在顶层 volumes 中定义的卷,例如 - db_data:/var/lib/mysql,Docker 会管理其生命周期,更适合生产环境的数据持久化。

配置示例

来看一个结合了多种配置的实战片段,这是一个典型的 Web 应用栈(Nginx + Node.js 应用 + MySQL):

version: '3.8'

services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf  # 挂载自定义配置
    depends_on:
      - app
    networks:
      - frontend

  app:
    build: ./app  # 使用 Dockerfile 构建镜像
    environment:
      - NODE_ENV=production
      - DATABASE_URL=mysql://user:password@db:3306/mydb
    volumes:
      - /app/node_modules  # 防止覆盖容器内目录
    depends_on:
      - db
    networks:
      - frontend
      - backend

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: mydb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    volumes:
      - db_data:/var/lib/mysql  # 使用命名卷持久化数据库
    networks:
      - backend

volumes:
  db_data:  # 声明命名卷

networks:
  frontend:
  backend:

在这个配置里,depends_on 确保了服务的启动顺序,而自定义网络 frontendbackend 则将服务分组并隔离,例如,将数据库 db 保护在后端网络中,只有 app 服务能直接访问。

Docker Compose 常用命令

创建并启动所有服务。-d 参数用于后台运行

docker compose up

停止并移除所有容器、网络

docker compose down

查看当前 Compose 启动的所有容器状态

docker compose ps

查看所有服务的日志。-f 参数可以持续跟踪

docker compose logs

重新构建服务的镜像

docker compose build

重启所有服务

docker compose restart

文章作者: Vsoapmac
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 soap的会员制餐厅
运维 docker
喜欢就支持一下吧