前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Docker容器化部署,这些最佳实践你不可不知

Docker容器化部署,这些最佳实践你不可不知

原创
作者头像
天创项目管理分享
发布2024-11-20 16:30:18
发布2024-11-20 16:30:18
41900
代码可运行
举报
文章被收录于专栏:DockerDocker
运行总次数:0
代码可运行

一、Docker 容器化部署简介

Docker 作为一种开源的容器化技术,在当今的软件开发和部署领域中发挥着至关重要的作用。它具有诸多显著优势,为开发者和运维人员带来了极大的便利。

首先,Docker 具有轻量级的特点。与传统的虚拟机相比,Docker 容器不需要运行完整的操作系统,只包含应用程序及其所需的依赖项,因此占用的资源更少,启动和停止速度更快。例如,Docker 容器可以在几秒钟内启动,而虚拟机可能需要几分钟甚至更长时间。

其次,可移植性是 Docker 的另一大优势。Docker 容器可以在任何支持 Docker 的平台上运行,无论是物理机、虚拟机还是云环境。这使得开发者可以在本地开发、测试应用程序,然后轻松地将其部署到不同的环境中,而无需担心环境差异导致的问题。

一致性也是 Docker 的重要特点之一。通过使用 Docker 镜像,开发者可以确保在不同的环境中运行的应用程序具有相同的配置和依赖项。这有助于减少因环境不一致而导致的问题,提高开发和部署的效率。

此外,Docker 还提供了良好的隔离性。每个 Docker 容器都在独立的进程中运行,相互之间不会干扰。这有助于确保应用程序的稳定性和安全性,同时也便于进行资源管理和分配。

总之,Docker 容器化部署技术凭借其轻量级、可移植、一致性和隔离性等优势,为开发者和运维人员提供了一种高效、可靠的应用程序部署方式。

二、安装与配置

(一)不同系统安装步骤

Windows 系统安装步骤:

  1. 安装 docker toolbox:https://docs.docker.com/toolbox/toolbox_install_windows/
  2. 安装 Oracle VM VirtualBox,注意选择最新版本,否则可能会创建不了镜像。地址:https://www.virtualbox.org/wiki/Downloads
  3. 双击启动,以管理员身份启动,下载镜像(一定以管理员身份)。手动下载地址:https://github.com/boot2docker/boot2docker/releases/download/v19.03.12/boot2docker.iso
  4. 替换位置如下:(默认位置)C:\Users\lihu\.docker\machine\machines\default。
  5. 替换阿里云加速镜像,阿里云镜像加速地址一般启动之后系统会默认创建镜像,因此执行如下命令:docker-machine rm -f default,然后按照阿里云的规则即可。
    • 创建一台安装有 Docker 环境的 Linux 虚拟机,指定机器名称为 default,同时配置 Docker 加速器地址:docker-machine create --engine-registry-mirror=https://*******.mirror.aliyuncs.com -d virtualbox default。
    • 查看机器的环境配置,并配置到本地,并通过 Docker 客户端访问 Docker 服务:docker-machine env default;eval "$(docker-machine env default)";docker info。

macOS 系统安装步骤:

可以使用 Homebrew 来安装 Docker。Homebrew 的 Cask 已经支持 Docker for Mac,因此可以很方便的使用 Homebrew Cask 来进行安装:输入命令:brew cask install docker。安装过程中,最终出现 docker was successfully installed!提示语时表示 docker 安装成功,最后在启动台里可以看到下载好的 docker.app。

Linux 系统安装步骤:

以 Centos7 为例:

  1. 安装前必读:Linux 内核官方建议 3.10 以上,3.8 以上貌似也可。注意:本文的命令使用的是 root 用户登录执行,不是 root 的话所有命令前面要加 sudo。
  2. 更新 yum 包:yum -y update。
  3. 卸载旧版本(如果以前安装过,否则此步骤可以忽略):yum remove docker-ce docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine。
  4. 安装相应的安装包:yum install -y yum-utils device-mapper-persistent-data lvm2。
  5. 设置 yum 源:yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo;yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo。
  6. 安装最新版本的 Docker Engine-Community 和 containerd.io:yum -y install docker-ce docker-ce-cli containerd.io。

(二)环境配置详解

设置存储位置:

  • 默认情况下 Docker 的存放位置为:/var/lib/docker,可以通过命令sudo docker info | grep "Docker Root Dir"查看具体位置。
  • 在 Linux 系统中,可以通过修改/etc/default/docker(Ubuntu)或/etc/sysconfig/docker(CentOS)配置文件,添加OPTIONS=--graph="/mnt/docker" --selinux-enabled -H fd://来指定镜像和容器存放路径。
  • 在 Windows 系统中,可以修改C:\\ProgramData\\docker\\config\\daemon.json文件,将data-root的值修改为想要设置的实际路径。

设置环境变量:

  • 在 Docker 容器内部定义环境变量是一种常见的做法。可以在 Dockerfile 中使用 ENV 命令来设置环境变量,或者在运行容器时使用--env参数指定环境变量。
  • 在 Docker Compose 文件中,可以使用 environment 关键字来定义环境变量,它可以在启动容器时自动加载。
  • 在某些情况下,将环境变量放在特定的配置文件中可能更方便。例如,在生产环境中,可能会使用多个配置文件来管理生产、测试、开发等不同的环境变量。在此情况下,可以使用 Dockerfile 中的 COPY 命令将配置文件复制到镜像中,并在运行容器时指定使用哪个配置文件。

调整启动参数:

  • Docker 启动参数主要是通过 Docker 命令和配置文件来设置的。常用的启动参数有:
    • -d:后台运行容器,并返回容器 ID。
    • --name:为容器指定一个名称。
    • -e:设置环境变量。
    • -p:指定端口映射,格式为:主机端口:容器端口。
    • -v:挂载一个目录或文件。
    • --restart:设置重启策略,如 always、on-failure 等。
    • --network:连接容器到一个网络。

例如,启动一个 nginx 容器,并将 80 端口映射到主机的 8080 端口:docker run -d -p 8080:80 --name my-nginx-container nginx。

三、基本命令

(一)镜像操作

搜索镜像:可以使用docker search命令从镜像仓库中查找所需镜像。例如,要查找所有包含“hello-world”的镜像,可以执行docker search hello-world。如果要查找收藏数大于 10 的包含“hello-world”的镜像,可以使用docker search -s 10 hello-world。

拉取镜像:使用docker pull命令可以从镜像仓库中拉取镜像。默认情况下,拉取的是最新版本的镜像,如docker pull hello-world就是拉取REPOSITORY为“hello-world”的最新镜像。如果要拉取特定版本,可以加上版本号,如docker pull hello-world:7.4。同时,也可以使用docker pull -a hello-world拉取“hello-world”的所有镜像。

查看镜像:docker images命令可以列出本地所有的非隐藏镜像。它有很多参数可以使用,比如-a参数可以列出本地所有的镜像(含中间映像层);--digests参数显示镜像的摘要信息;--format参数可以指定返回值的模板文件;--no-trunc参数显示完整的镜像信息;-q只显示镜像 ID。

删除镜像:使用docker rmi命令可以删除本地没有被容器占用的镜像。如果要强制删除,可以加上-f参数,但需注意如果镜像关联了容器,强制删除可能会导致数据丢失或不一致。例如,docker rmi image_name/image_id删除本地没有被容器占用的镜像,docker rmi image_name/image_id -f强制删除本地镜像。

构建镜像:可以通过 Dockerfile 构建镜像,使用docker build -f Dockerfile的文件路径 -t 新镜像名字:TAG.命令。在当前目录下,如果不指定-f参数,默认读取名字为 Dockerfile 的文件,-t选项用于给构建的镜像标记名称和标签。

(二)容器操作

运行容器:使用docker run命令可以启动一个新的容器。这个命令有很多参数,比如--name可以给容器设置一个名称;-d可以后台运行容器,并返回容器 ID;-i和-t参数一起使用可以以交互模式运行容器,并分配一个伪输入终端;-e可以设置环境变量;-p可以指定端口映射;-v可以挂载一个目录或文件。例如,docker run -d -p 8080:80 --name my-nginx-container nginx启动一个 nginx 容器,并将 80 端口映射到主机的 8080 端口,同时给容器命名为“my-nginx-container”。

查看容器:docker ps命令可以列出当前所有正在运行的容器。-a参数可以列出当前所有正在运行的容器以及历史上运行过的容器;-l显示最近创建的容器;-n显示最近 n 个创建的容器;-q只显示容器编号;--no-trunc不截断输出。

停止容器:使用docker stop命令可以优雅地停止正在运行的容器,允许容器内的应用程序执行清理操作。如果需要立即停止容器,可以使用docker kill命令,但这可能会导致数据丢失或不一致。

启动容器:如果需要启动一个之前停止的容器,可以使用docker start命令。

删除容器:使用docker rm命令可以删除已停止的容器。如果要强制删除正在运行的容器,可以加上-f参数,但需谨慎使用。也可以使用docker rm -f $(docker ps -a -q)或docker ps -a -q | xargs docker rm一次性删除全部已停止的容器。

进入容器终端:有三种方法可以进入 Docker 容器终端。方法一:使用docker exec -it <container_id> <command>命令,其中-it参数表示要进入交互式终端,<container_id>是容器的标识符,<command>是要在容器中执行的命令。方法二:使用docker attach <container_id>命令,可以将当前终端附加到一个正在运行的容器中,但退出时不能使用exit,否则会导致容器停止,可以使用Ctrl + C退出。方法三:使用docker run -it <image_name> <command>命令,可以直接在容器内部启动一个新的终端。

查看容器日志:使用docker logs命令可以查看容器的日志。可以使用-f参数实时跟踪容器的日志输出;--since参数显示自某个 timestamp 之后的日志;--tail参数从日志末尾显示多少行日志;-t参数显示时间戳;--until参数显示自某个 timestamp 之前的日志。例如,docker logs -f -t --since="2018-02-08" --tail=100 CONTAINER_ID查看指定时间后的日志,只显示最后 100 行。

四、容器化部署基础

(一)Dockerfile 编写

  1. 基本语法,如 FROM、COPY、RUN、CMD 等指令的作用。
    • FROM指令用于指定基础镜像,是构建新镜像的起点。例如,FROM ubuntu:20.04表示以 Ubuntu 20.04 版本的镜像作为基础镜像。
    • COPY指令用于将文件或目录从构建上下文复制到镜像中。例如,COPY./app /app表示将当前目录下的app文件夹复制到镜像中的/app目录。
    • RUN指令用于在镜像中执行命令,通常用于安装软件包、配置环境等。例如,RUN apt-get update && apt-get install -y nginx表示更新软件包列表并安装 Nginx。
    • CMD指令用于指定容器启动时默认执行的命令。例如,CMD [\"python\", \"app.py\"]表示容器启动时运行app.py文件。
  2. 常用指令解析,结合实际示例进行说明。
    • ENV指令用于设置环境变量。例如,ENV APP_ENV=production设置了名为APP_ENV,值为production的环境变量。在构建镜像以及运行容器时,这个环境变量都可用。
    • ADD指令与COPY类似,但功能更为强大。除了复制文件外,ADD还可以解压缩 tar 文件并支持 URL。例如,ADD myapp.tar.gz /app表示将一个名为myapp.tar.gz的压缩文件解压缩并复制到镜像中的/app目录。
    • WORKDIR指令用于设置工作目录,后续的指令(如RUN、CMD、ENTRYPOINT等)都将在这个目录下执行。例如,WORKDIR /app设置工作目录为/app。
  3. 编写实例,展示如何构建单个容器应用的镜像。
代码语言:javascript
代码运行次数:0
复制
FROM python:3.9WORKDIR /appCOPY. /appRUN pip install -r requirements.txtCMD [\"python\", \"app.py\"]

(二)Docker Compose 入门

  1. 文件结构和编写方法。
代码语言:javascript
代码运行次数:0
复制
version: '3'services:  web:    image: nginx:latest    ports:      - "80:80"
  1. 用其部署多容器应用的步骤。
代码语言:javascript
代码运行次数:0
复制
version: '3'services:  web:    image: my-web-app:latest    ports:      - "8080:80"    depends_on:      - db  db:    image: mysql:latest    environment:      MYSQL_ROOT_PASSWORD: password

五、实战演练

(一)Flask 应用部署

Flask 是一个用 Python 编写的轻量级 Web 应用框架。以下是使用 Docker 和 Docker Compose 部署 Flask 应用的全过程。

  1. 创建 Flask 应用

首先,创建一个基本的 Flask 应用。例如,创建一个名为app.py的文件,并写入以下代码:

代码语言:javascript
代码运行次数:0
复制
from flask import Flaskapp = Flask(__name__)@app.route('/')def hello_world():    return 'Hello, World!'if __name__ == '__main__':    app.run(host='0.0.0.0', port=8000)
  1. 编写 Dockerfile

创建一个名为Dockerfile的文件,并写入以下内容:

代码语言:javascript
代码运行次数:0
复制
# 使用官方 Python 运行时作为父镜像FROM python:3.8-slim# 设置工作目录WORKDIR /app# 复制 requirements.txt 到工作目录(先创建这个文件)COPY requirements.txt.# 安装 Gunicorn 和 Flask 应用的依赖RUN pip install --no-cache-dir -r requirements.txt# 复制当前目录下的所有文件到工作目录COPY..# 声明运行时的端口EXPOSE 8000# 运行 Gunicorn 服务器CMD ["gunicorn", "-w", "4", "app:app"]
  1. 准备依赖文件

创建一个requirements.txt文件,列出所有依赖项,例如:

代码语言:javascript
代码运行次数:0
复制
Flask==1.1.2gunicorn==20.0.4
  1. 构建 Docker 镜像

使用以下命令构建 Docker 镜像:

代码语言:javascript
代码运行次数:0
复制
docker build -t my-flask-app.
  1. 编写 docker-compose.yml 文件
代码语言:javascript
代码运行次数:0
复制
version: '3'services:  flask-app:    build:.    ports:      - "8000:8000"
  1. 运行 Docker 容器

使用以下命令运行 Docker 容器:

代码语言:javascript
代码运行次数:0
复制
docker-compose up

访问应用在浏览器中访问http://localhost:8000,你应该能看到"Hello, World!"的消息。

(二)Web 应用部署

以 PHP 应用搭配 Nginx 和 MySQL 为例进行容器化部署和持续集成。

  1. 选择基础镜像

对于 PHP 应用,可以选择官方的php:7.4-fpm镜像作为基础镜像,对于 Nginx 可以选择nginx:latest镜像,对于 MySQL 可以选择mysql:latest镜像。

  1. 编写 Dockerfile

对于 PHP 应用,创建一个Dockerfile文件如下:

代码语言:javascript
代码运行次数:0
复制
FROM php:7.4-fpm# 设置工作目录WORKDIR /app# 复制 composer.json 和 composer.lock 文件COPY composer.json composer.lock /app/# 安装 Composer 依赖RUN composer install# 复制项目文件COPY. /app/
  1. 编写 nginx 配置文件

创建一个nginx.conf文件如下:

代码语言:javascript
代码运行次数:0
复制
worker_processes  1;events {    worker_connections  1024;}http {    sendfile          on;    tcp_nodelay       on;    keepalive_timeout  30;    include /etc/nginx/mime.types;    default_type application/octet-stream;    server {        listen 80;        server_name localhost;        root   /usr/share/nginx/html;        index  index.php index.html;        location / {            try_files $uri $uri/ =404;        }        location ~ \\.php$ {            fastcgi_pass   php:9000;            fastcgi_index  index.php;            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;            include        fastcgi_params;        }    }}
  1. 编写 docker-compose.yml 文件
代码语言:javascript
代码运行次数:0
复制
version: '3'services:  php:    build:.    volumes:      -./app:/app  nginx:    image: nginx:latest    volumes:      -./nginx.conf:/etc/nginx/nginx.conf      -./app:/usr/share/nginx/html    depends_on:      - php  mysql:    image: mysql:latest    environment:      MYSQL_ROOT_PASSWORD: password
  1. 运行容器

在命令行中进入包含docker-compose.yml文件的目录,执行docker-compose up命令启动应用。

  1. 持续集成

可以使用工具如 Jenkins 或 GitLab CI/CD 进行持续集成。例如,在 GitLab CI/CD 中,可以定义一个.gitlab-ci.yml文件,在代码提交后自动构建镜像、运行测试并部署到生产环境。

以下是一个简单的.gitlab-ci.yml文件示例:

代码语言:javascript
代码运行次数:0
复制
stages:  - build  - test  - deploybuild:  stage: build  script:    - docker-compose buildtest:  stage: test  script:    - docker-compose run --rm php phpunitdeploy:  stage: deploy  script:    - docker-compose push    - ssh <server_ip> "docker-compose pull && docker-compose up -d"

通过以上步骤,可以实现 PHP 应用搭配 Nginx 和 MySQL 的容器化部署和持续集成。

六、注意事项与最佳实践

(一)注意事项

1. 容器通信时配置文件的 IP 地址设置

在 Docker 容器化部署中,容器通信时配置文件的 IP 地址设置至关重要。Docker 提供了多种网络模式,如 bridge、host、overlay 等。以 bridge 网络模式为例,当创建一个新的 Docker 容器时,可以进入容器内部编辑网络配置文件来设置静态 IP 地址。例如,在大多数 Linux 发行版中,网络配置文件位于 /etc/network/interfaces 路径下。可以添加以下内容来为容器分配特定的 IP 地址:

代码语言:javascript
代码运行次数:0
复制
auto eth0iface eth0 inet staticaddress 192.168.0.100netmask 255.255.255.0gateway 192.168.0.1dns-nameservers 8.8.8.8

这样配置将为容器分配 IP 地址 192.168.0.100,子网掩码 255.255.255.0,网关 192.168.0.1,DNS 服务器 8.8.8.8。保存并退出文件后,需要重新启动网络服务才能使配置生效,可使用 service networking restart 命令。验证 IP 配置是否成功,可以在 Docker 容器中运行 ifconfig 命令,在输出中应该能够看到刚刚配置的静态 IP 地址。

2. 使用 Kubernetes/Docker 部署应用时保密字典的运用

在使用 Kubernetes 进行部署时,应用中通常会涉及到数据库或其他中间件的访问连接,这些连接一般都需要账号、密码等敏感信息。为了确保这些敏感信息的安全,可使用保密字典(Secret)。例如,在 deployment yaml 文件中引入 secret,以数据卷卷方式进行挂载,如下:

代码语言:javascript
代码运行次数:0
复制
apiVersion: apps/v1beta2kind: Deploymentmetadata:  name: "${APP_NAME}"  labels:    app: ${APP_NAME}  namespace: your_servicespec:  replicas: 1  selector:    matchLabels:      app: ${APP_NAME}      track: stable  template:    metadata:      labels:        app: ${APP_NAME}        track: stable    spec:      imagePullSecrets:        - name: registry-key      containers:        - name: ${APP_NAME}          image: ${IMAGE_URL}          imagePullPolicy: Always          resources: {}          volumeMounts:            - name: volume-your_service-config              mountPath: /path/to/config      volumes:        - name: volume-your_service-config          secret:            secretName: your-secret-name

Kubernetes 保密字典可用于存储和管理密码、OAuth 令牌和 SSH 保密字典等敏感信息。容器组可以通过三种方式使用保密字典:作为挂载到容器组中容器化应用上的卷中的文件;作为容器组中容器使用的环境变量;作为 kubelet 为容器组拉取镜像时的镜像仓库凭证。

(二)最佳实践

1. 使用官方镜像及特定版本

使用官方镜像可以确保镜像的安全性和稳定性。同时,指定特定版本可以避免由于不同版本导致的兼容性问题。例如,要拉取官方的 Nginx 镜像的 1.19.7 版本,可以使用以下命令:docker pull nginx:1.19.7。在 Dockerfile 中指定依赖包的版本也可以确保应用程序的稳定性和一致性。如在构建基于 Node.js 的 Web 应用程序时,可以在 package.json 文件中指定 Express 和 Mongoose 的版本:

代码语言:javascript
代码运行次数:0
复制
{  "name": "myapp",  "version": "1.0.0",  "dependencies": {    "express": "^4.17.1",    "mongoose": "^5.12.3"  }}
2. 扫描镜像查找安全漏洞

根据绿盟 2018 年 3 月的研究显示,目前 Docker Hub 上的镜像 76%都存在漏洞。因此,进行镜像安全扫描是非常必要的。可以使用工具如 Trivy、Clair 或 Anchore 进行漏洞扫描。例如,使用 Trivy 进行漏洞扫描的命令为:trivy image my-image:latest。为了确保每次构建的镜像都经过漏洞扫描,可以将漏洞扫描集成到持续集成/持续部署(CI/CD)管道中。

3. 使用小型镜像

使用小型镜像可以加快上线、重启和增加新节点的速度,减少中断服务的时间,同时占用的镜像仓库存储也少。可以选择小的基础镜像如 Alpine Linux 或 Debian 的 slim 版本,或者使用空镜像(FROM scratch)进行构建。例如,使用以下 Dockerfile 可以构建一个小的 Go 语言应用镜像:

代码语言:javascript
代码运行次数:0
复制
FROM golang:alpine AS build-envWORKDIR /appADD. /appENV GOOS=linux GOARCH=amd64 CGO_ENABLED=0RUN cd /app && go build -ldflags -s -a -installsuffix cgo webServer.go && ls -lhFROM scratchWORKDIR /appCOPY --from=build-env /app/webServer /EXPOSE 8080CMD ["/webServer"]
4. 优化缓存镜像层

为了进一步优化镜像的大小,可以使用多个 RUN 命令,而不是一个复杂的命令来安装软件包。这样可以减少镜像的历史层,从而减小镜像的大小。例如:

代码语言:javascript
代码运行次数:0
复制
FROM alpine:latest# 安装依赖项RUN apk add --no-cache \\package1 \\package2 \\package3# 清理缓存和临时文件RUN rm -rf /var/cache/apk/* /tmp/*
5. 使用.dockerignore 文件

使用 .dockerignore 文件可以排除不需要的文件和目录,避免将不必要的文件复制到镜像中,从而减小镜像的大小。例如,可以在 .dockerignore 文件中添加以下内容:

代码语言:javascript
代码运行次数:0
复制
node_modules.DS_Store
6. 遵循最小权限用户原则

在容器中运行应用程序时,应该遵循最小权限用户原则,避免使用 root 用户运行应用程序。可以在 Dockerfile 中创建一个新用户,并使用该用户运行应用程序。例如:

代码语言:javascript
代码运行次数:0
复制
FROM ubuntu:latestRUN useradd -m appuserWORKDIR /appCOPY. /appRUN chown -R appuser:appuser /appUSER appuserCMD ["./app"]

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Docker 容器化部署简介
  • 二、安装与配置
    • (一)不同系统安装步骤
    • (二)环境配置详解
  • 三、基本命令
    • (一)镜像操作
    • (二)容器操作
  • 四、容器化部署基础
    • (一)Dockerfile 编写
    • (二)Docker Compose 入门
  • 五、实战演练
    • (一)Flask 应用部署
    • (二)Web 应用部署
  • 六、注意事项与最佳实践
    • (一)注意事项
      • 1. 容器通信时配置文件的 IP 地址设置
      • 2. 使用 Kubernetes/Docker 部署应用时保密字典的运用
    • (二)最佳实践
      • 1. 使用官方镜像及特定版本
      • 2. 扫描镜像查找安全漏洞
      • 3. 使用小型镜像
      • 4. 优化缓存镜像层
      • 5. 使用.dockerignore 文件
      • 6. 遵循最小权限用户原则
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档