规范门户网站的建设和管理办法在线商标免费设计
2026/5/18 20:44:27 网站建设 项目流程
规范门户网站的建设和管理办法,在线商标免费设计,安徽省交通运输厅门户网站,兰州网站建设公最近总有朋友问我Docker到底是个啥#xff0c;怎么用#xff0c;感觉很高大上但又不知道从哪里下手。说实话#xff0c;我刚开始接触Docker的时候也是一脸懵逼#xff0c;各种概念搞得头大。不过用了几年下来#xff0c;现在回头看#xff0c;Docker真的是个好东西#…最近总有朋友问我Docker到底是个啥怎么用感觉很高大上但又不知道从哪里下手。说实话我刚开始接触Docker的时候也是一脸懵逼各种概念搞得头大。不过用了几年下来现在回头看Docker真的是个好东西能解决很多实际问题。今天就来聊聊Docker的实际使用不讲那些虚头巴脑的理论直接上干货。我会把自己这几年踩过的坑、用过的技巧都分享出来希望能帮到大家。什么是Docker为什么要用它Docker说白了就是一个容器技术可以把应用程序和它的运行环境打包在一起。你可以理解为一个轻量级的虚拟机但比虚拟机要快很多。我记得以前部署应用的时候经常遇到在我电脑上能跑啊这种问题。开发环境Python 3.8测试环境Python 3.7生产环境又是3.9各种版本冲突搞得人头疼。有了Docker之后这些问题基本就不存在了因为环境都打包好了到哪里都一样。还有一个好处就是资源利用率高。以前一台服务器可能只跑一个应用现在可以跑十几个容器每个容器都是独立的互不影响。安装Docker安装Docker其实很简单官网都有详细的文档。不过我还是说几个注意点。在Ubuntu上安装# 更新包索引sudoaptupdate# 安装必要的包sudoaptinstallapt-transport-https ca-certificatescurlgnupg lsb-release# 添加Docker官方GPG密钥curl-fsSL https://download.docker.com/linux/ubuntu/gpg|sudogpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg# 设置稳定版仓库echodeb [archamd64 signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu$(lsb_release -cs)stable|sudotee/etc/apt/sources.list.d/docker.list/dev/null# 安装Docker Enginesudoaptupdatesudoaptinstalldocker-ce docker-ce-cli containerd.io安装完成后记得把当前用户加入docker组这样就不用每次都sudo了sudousermod-aG docker$USER然后重新登录一下或者执行newgrp docker。CentOS的安装过程类似就是包管理器换成yum。Windows和Mac的话直接下载Docker Desktop就行了图形界面操作很方便。Docker的基本概念在开始实际操作之前先理解几个核心概念。镜像Image可以理解为一个模板包含了运行应用所需的所有东西。比如一个Ubuntu镜像就包含了Ubuntu系统的基本文件。容器Container镜像运行起来就是容器。一个镜像可以创建多个容器就像一个类可以实例化多个对象一样。仓库Repository存放镜像的地方Docker Hub是最大的公共仓库。这三个概念搞清楚了后面的操作就好理解了。常用Docker命令镜像相关命令查看本地镜像docker images拉取镜像docker pull nginx:latest docker pull ubuntu:20.04删除镜像docker rmi nginx:latest构建镜像docker build -t myapp:v1.0.容器相关命令运行容器# 最基本的运行docker run hello-world# 交互式运行docker run -it ubuntu:20.04 /bin/bash# 后台运行docker run -d nginx:latest# 端口映射docker run -d -p8080:80 nginx:latest查看容器# 查看正在运行的容器dockerps# 查看所有容器包括停止的dockerps-a停止和启动容器docker stop container_id docker start container_id docker restart container_id进入容器dockerexec-it container_id /bin/bash删除容器dockerrmcontainer_id查看容器日志docker logs container_id docker logs -f container_id# 实时查看实战案例部署一个Web应用说了这么多理论来个实际例子。我们部署一个简单的Flask应用。首先创建一个Flask应用文件名app.pyfromflaskimportFlask appFlask(__name__)app.route(/)defhello():returnh1Hello from Docker!/h1app.route(/health)defhealth():return{status:ok}if__name____main__:app.run(host0.0.0.0,port5000)创建requirements.txtFlask2.3.3然后写Dockerfile# 使用Python 3.9作为基础镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 复制requirements文件 COPY requirements.txt . # 安装依赖 RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY app.py . # 暴露端口 EXPOSE 5000 # 运行应用 CMD [python, app.py]构建镜像docker build -t flask-app:v1.0.运行容器docker run -d -p5000:5000 --name my-flask-app flask-app:v1.0现在访问http://localhost:5000就能看到应用了。这个例子看起来简单但包含了Docker的核心用法。在实际项目中可能还需要考虑数据持久化、环境变量配置等问题。数据持久化和卷Volume容器默认是无状态的容器删除后数据就没了。但很多时候我们需要持久化数据比如数据库文件、日志文件等。Docker提供了几种数据持久化的方式绑定挂载Bind Mount直接把主机的目录挂载到容器里docker run -d -v /host/path:/container/path nginx:latest比如运行一个MySQL容器把数据目录挂载到主机docker run -d\--name mysql-server\-eMYSQL_ROOT_PASSWORDmypassword\-v /opt/mysql-data:/var/lib/mysql\-p3306:3306\mysql:8.0这样即使容器删除了数据库文件还在主机的/opt/mysql-data目录里。Docker卷Volume这是Docker推荐的方式# 创建卷docker volume create mydata# 使用卷docker run -d -v mydata:/data nginx:latest# 查看卷docker volumels# 查看卷详情docker volume inspect mydata卷的好处是由Docker管理不用担心路径问题而且可以在容器间共享。临时文件系统tmpfs把数据存储在内存中容器停止后数据就没了docker run -d --tmpfs /tmp nginx:latest这种方式适合存储临时数据比如缓存文件。Docker网络详解Docker的网络功能很强大也是很多人觉得复杂的地方。我刚开始学的时候也被搞得晕头转向不过理解了原理之后就清晰多了。Docker网络架构Docker使用Linux的网络命名空间来实现容器网络隔离。每个容器都有自己的网络栈包括网卡、路由表、防火墙规则等。Docker在宿主机上创建了一个虚拟网桥docker0默认情况下所有容器都连接到这个网桥上。容器之间可以通过这个网桥进行通信。默认网络模式Docker提供了几种网络模式bridge模式默认容器连接到docker0网桥有自己的IP地址可以和其他容器通信。docker run -d --name web nginx:latesthost模式容器直接使用宿主机的网络没有网络隔离。docker run -d --networkhostnginx:latest这种模式下容器的网络性能最好但失去了隔离性。none模式容器没有网络接口完全隔离。docker run -d --network none nginx:latestcontainer模式容器共享另一个容器的网络。docker run -d --name web nginx:latest docker run -d --network container:web busybox:latest查看默认网络Docker安装后会创建几个默认网络docker networkls通常会看到这些网络bridge默认网桥网络host主机网络none无网络查看网络详情docker network inspect bridge这个命令会显示网络的配置信息包括子网、网关、连接的容器等。自定义网络自定义网络是Docker网络的精髓可以实现更灵活的网络配置。创建bridge网络# 创建自定义网络docker network create mynetwork# 指定子网和网关docker network create --driver bridge\--subnet172.20.0.0/16\--ip-range172.20.240.0/20\--gateway172.20.0.1\mynetwork2使用自定义网络# 运行容器时指定网络docker run -d --network mynetwork --name web nginx:latest docker run -d --network mynetwork --name db mysql:8.0# 给运行中的容器连接网络docker network connect mynetwork existing_container自定义网络的优势在自定义网络中容器可以通过容器名相互访问这是默认bridge网络没有的功能# 创建网络和容器docker network create webapp docker run -d --network webapp --name database mysql:8.0 docker run -d --network webapp --name backend node-app:latest docker run -d --network webapp --name frontend nginx:latest# backend容器可以通过database这个主机名访问数据库# frontend容器可以通过backend访问后端API这个功能叫做自动服务发现非常实用。网络连接和断开容器可以同时连接多个网络# 创建两个网络docker network create frontend docker network create backend# 容器连接到多个网络docker run -d --network frontend --name web nginx:latest docker network connect backend web# 断开网络连接docker network disconnect frontend web这样可以实现更复杂的网络拓扑比如三层架构中的网络隔离。端口映射详解端口映射让外部可以访问容器内的服务有几种方式基本端口映射# 映射单个端口宿主机8080端口映射到容器80端口docker run -d -p8080:80 nginx:latest# 映射多个端口docker run -d -p8080:80 -p8443:443 nginx:latest# 映射到指定IPdocker run -d -p127.0.0.1:8080:80 nginx:latest# 随机映射端口docker run -d -P nginx:latestUDP端口映射# TCP端口默认docker run -d -p53:53 dns-server:latest# UDP端口docker run -d -p53:53/udp dns-server:latest# 同时映射TCP和UDPdocker run -d -p53:53/tcp -p53:53/udp dns-server:latest查看端口映射# 查看容器端口映射docker port container_name# 查看所有容器的端口dockerps--formattable {{.Names}}\t{{.Ports}}容器间通信实例来个实际例子部署一个Web应用包含前端、后端、数据库# 创建自定义网络docker network create webapp --subnet172.18.0.0/16# 启动数据库容器docker run -d\--name database\--network webapp\--ip172.18.0.10\-eMYSQL_ROOT_PASSWORDrootpass\-eMYSQL_DATABASEmyapp\mysql:8.0# 启动后端API容器docker run -d\--name api\--network webapp\--ip172.18.0.20\-eDATABASE_HOSTdatabase\-eDATABASE_PORT3306\my-api:latest# 启动前端容器docker run -d\--name frontend\--network webapp\--ip172.18.0.30\-p80:80\-eAPI_HOSTapi\-eAPI_PORT3000\my-frontend:latest在这个例子中数据库容器不需要暴露端口到宿主机只在内部网络中通信API容器可以通过database主机名访问数据库前端容器可以通过api主机名访问后端只有前端容器暴露端口给外部访问网络故障排查当容器网络出问题时可以用这些方法排查检查容器网络配置# 查看容器的网络配置docker inspect container_name|grep-A20NetworkSettings# 查看容器IP地址docker inspect container_name|grepIPAddress进入容器测试网络# 进入容器dockerexec-it container_name /bin/bash# 测试网络连通性pinganother_container telnet database3306curlhttp://api:3000/health# 查看网络接口ipaddr show route -n在容器内安装网络工具# Debian/Ubuntu容器apt-getupdateapt-getinstall-y iputils-pingcurltelnet net-tools# Alpine容器apkadd--no-cache iputilscurl# CentOS容器yuminstall-y iputilscurltelnet net-tools宿主机网络检查# 查看docker网桥ipaddr show docker0 brctl show docker0# 查看iptables规则iptables -L -n iptables -t nat -L -n# 查看网络命名空间ipnetns list跨主机网络当应用需要在多台服务器上运行时就需要跨主机网络了。Docker提供了几种方案Docker Swarm网络# 初始化Swarm集群docker swarm init --advertise-addr192.168.1.100# 在其他节点加入集群docker swarmjoin--tokentoken192.168.1.100:2377# 创建overlay网络docker network create -d overlay myoverlay# 部署服务到overlay网络dockerservicecreate --network myoverlay --name web nginx:latestOverlay网络让不同主机上的容器可以直接通信就像在同一台机器上一样。第三方网络插件比如Calico、Flannel、Weave等提供更高级的网络功能。网络安全容器网络安全也很重要几个建议网络隔离# 创建独立的网络避免容器间不必要的通信docker network create --internal backend-only docker run -d --network backend-only database:latest防火墙规则# Docker会自动添加iptables规则但可以手动调整iptables -I DOCKER-USER-s172.17.0.0/16 -d192.168.1.0/24 -j DROP使用非特权端口# 避免使用特权端口1-1024docker run -d -p8080:80 nginx:latest# 好docker run -d -p80:80 nginx:latest# 不推荐网络性能优化选择合适的网络模式对性能要求极高的应用可以使用host模式一般应用使用bridge模式就够了需要网络隔离的用自定义网络调整网络参数# 修改docker daemon配置cat/etc/docker/daemon.jsonEOF { bip: 172.17.0.1/16, mtu: 1500, default-address-pools: [ { base: 172.80.0.0/12, size: 24 } ] } EOF监控网络流量# 查看容器网络统计docker stats --formattable {{.Container}}\t{{.NetIO}}# 使用iftop监控网络流量dockerexec-it container_name iftop环境变量和配置很多应用需要通过环境变量进行配置Docker提供了几种方式运行时指定docker run -d -eMYSQL_ROOT_PASSWORDmypassword mysql:8.0 docker run -d -eNODE_ENVproduction -ePORT3000node-app:latest使用env文件创建.env文件MYSQL_ROOT_PASSWORDmypassword MYSQL_DATABASEmyapp MYSQL_USERappuser MYSQL_PASSWORDapppassword然后运行docker run -d --env-file .env mysql:8.0这种方式比较安全敏感信息不会出现在命令行里。在Dockerfile中设置默认值FROM node:16 ENV NODE_ENVproduction ENV PORT3000 # ...Docker Compose多容器应用的救星当应用变复杂需要多个容器协同工作时一个个手动启动容器就很麻烦了。Docker Compose就是来解决这个问题的。安装Docker Compose现在的Docker Desktop都自带了ComposeLinux上可能需要单独安装sudocurl-Lhttps://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname-s)-$(uname-m)-o /usr/local/bin/docker-composesudochmodx /usr/local/bin/docker-compose编写docker-compose.yml比如一个典型的Web应用需要Web服务器、数据库、Redis缓存version:3.8services:web:build:.ports:-5000:5000environment:-DATABASE_URLmysql://user:passworddb:3306/myapp-REDIS_URLredis://redis:6379depends_on:-db-redisvolumes:-./logs:/app/logsnetworks:-frontend-backenddb:image:mysql:8.0environment:MYSQL_ROOT_PASSWORD:rootpasswordMYSQL_DATABASE:myappMYSQL_USER:userMYSQL_PASSWORD:passwordvolumes:-mysql_data:/var/lib/mysqlnetworks:-backendredis:image:redis:7-alpinenetworks:-backendnginx:image:nginx:alpineports:-80:80volumes:-./nginx.conf:/etc/nginx/nginx.confdepends_on:-webnetworks:-frontendnetworks:frontend:driver:bridgebackend:driver:bridgeinternal:truevolumes:mysql_data:这个例子展示了网络分层frontend网络连接nginx和web服务backend网络连接web、db和redisbackend网络设置为internal外部无法直接访问使用Compose命令# 启动所有服务docker-compose up -d# 查看服务状态docker-composeps# 查看日志docker-compose logs web docker-compose logs -f# 实时查看所有服务日志# 停止服务docker-compose stop# 停止并删除容器docker-compose down# 重新构建并启动docker-compose up -d --build用了Compose之后管理多容器应用就轻松多了。一个命令就能启动整个应用栈而且服务之间的依赖关系也处理得很好。实际生产环境的最佳实践镜像优化镜像大小直接影响部署速度所以要尽量优化使用多阶段构建# 构建阶段 FROM node:16 AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction # 运行阶段 FROM node:16-alpine WORKDIR /app COPY --frombuilder /app/node_modules ./node_modules COPY . . EXPOSE 3000 CMD [node, server.js]选择合适的基础镜像alpine版本通常比较小slim版本是精简版比完整版小很多如果不需要包管理器可以用distroless镜像清理不必要的文件RUN apt-get update apt-get install -y \ package1 \ package2 \ rm -rf /var/lib/apt/lists/*安全考虑不要用root用户运行应用RUN addgroup -g 1001 -S nodejs RUN adduser -S nextjs -u 1001 USER nextjs扫描镜像漏洞docker scan myapp:latest使用.dockerignorenode_modules npm-debug.log .git .gitignore README.md .env .nyc_output coverage .nyc_output健康检查HEALTHCHECK --interval30s --timeout3s --start-period5s --retries3 \ CMD curl -f http://localhost:3000/health || exit 1在Compose中services:web:build:.healthcheck:test:[CMD,curl,-f,http://localhost:3000/health]interval:30stimeout:10sretries:3start_period:40s日志管理Docker默认的json-file日志驱动会让日志文件越来越大生产环境建议配置日志轮转docker run -d\--log-driver json-file\--log-opt max-size10m\--log-opt max-file3\nginx:latest或者使用外部日志系统比如ELK Stack。监控和调试查看容器资源使用情况# 实时查看docker stats# 查看特定容器docker stats container_name进入容器调试# 进入运行中的容器dockerexec-it container_name /bin/bash# 如果没有bash试试shdockerexec-it container_name /bin/sh查看容器详细信息docker inspect container_name这个命令会输出容器的所有配置信息包括网络、挂载点、环境变量等调试时很有用。容器内安装调试工具有时候需要在容器内安装一些调试工具# 在Debian/Ubuntu容器内apt-getupdateapt-getinstall-ycurlvimnet-tools# 在Alpine容器内apkadd--no-cachecurlvim不过这种方式只是临时的容器重启后就没了。常见问题和解决方案容器启动失败首先查看日志docker logs container_name常见原因端口被占用环境变量配置错误挂载路径不存在权限问题容器内时间不对容器默认使用UTC时间如果需要本地时间docker run -d -v /etc/localtime:/etc/localtime:ro myapp:latest或者设置时区环境变量docker run -d -eTZAsia/Shanghai myapp:latest镜像拉取慢国内网络环境下从Docker Hub拉取镜像可能很慢可以配置镜像加速器。编辑/etc/docker/daemon.json{registry-mirrors:[https://docker.mirrors.ustc.edu.cn,https://hub-mirror.c.163.com]}然后重启Docker服务sudosystemctl restart docker容器间通信问题确保容器在同一个网络中或者使用link虽然已经deprecateddocker run -d --name db mysql:8.0 docker run -d --link db:database web-app:latest不过建议还是用自定义网络更灵活。数据丢失问题记住容器是无状态的重要数据一定要持久化。数据库、配置文件、日志文件都要挂载到主机或者Docker卷。Docker在CI/CD中的应用Docker在持续集成和持续部署中发挥了重要作用。GitLab CI示例stages:-build-test-deployvariables:DOCKER_IMAGE:$CI_REGISTRY_IMAGE:$CI_COMMIT_SHAbuild:stage:buildscript:-docker build-t $DOCKER_IMAGE .-docker push $DOCKER_IMAGEtest:stage:testscript:-docker run--rm $DOCKER_IMAGE npm testdeploy:stage:deployscript:-docker pull $DOCKER_IMAGE-docker stop myapp||true-docker rm myapp||true-docker run-d--name myapp-p 80:3000 $DOCKER_IMAGEonly:-mainGitHub Actions示例name:Build and Deployon:push:branches:[main]jobs:build-and-deploy:runs-on:ubuntu-lateststeps:-uses:actions/checkoutv2-name:Build Docker imagerun:docker build-t myapp:${{github.sha}}.-name:Run testsrun:docker run--rm myapp:${{github.sha}}npm test-name:Deployrun:|docker stop myapp || true docker rm myapp || true docker run -d --name myapp -p 80:3000 myapp:${{ github.sha }}这样每次代码提交后就会自动构建镜像、运行测试、部署应用。性能优化技巧减少镜像层数每个RUN、COPY、ADD指令都会创建一个新的镜像层尽量合并# 不好的做法 RUN apt-get update RUN apt-get install -y package1 RUN apt-get install -y package2 # 好的做法 RUN apt-get update apt-get install -y \ package1 \ package2 \ rm -rf /var/lib/apt/lists/*利用构建缓存Docker会缓存镜像层把变化频繁的指令放在后面# 先复制依赖文件 COPY package.json package-lock.json ./ RUN npm ci # 再复制源代码 COPY . .这样源代码变化时依赖安装的缓存还能用。使用.dockerignore类似.gitignore避免把不必要的文件复制到镜像中node_modules .git .gitignore README.md Dockerfile .dockerignore选择合适的基础镜像开发环境可以用完整版镜像方便调试生产环境用精简版减少攻击面和镜像大小如果追求极致性能可以用scratch或distrolessDocker网络高级配置刚才讲了基础的网络知识现在来看看一些高级配置。MacVLAN网络MacVLAN可以让容器直接获得物理网络的IP地址就像虚拟机一样# 创建MacVLAN网络docker network create -d macvlan\--subnet192.168.1.0/24\--gateway192.168.1.1\-oparenteth0\macvlan-net# 运行容器docker run -d --network macvlan-net --ip192.168.1.100 nginx:latest这种方式的好处是容器可以直接和物理网络中的设备通信不需要端口映射。但缺点是需要网络管理员分配IP地址而且不是所有的网络环境都支持。IPvlan网络IPvlan类似MacVLAN但使用同一个MAC地址docker network create -d ipvlan\--subnet192.168.1.0/24\--gateway192.168.1.1\-oparenteth0\-oipvlan_model2\ipvlan-netIPvlan有两种模式L2模式类似MacVLAN但共享MAC地址L3模式路由模式需要配置路由规则网络别名在自定义网络中可以给容器设置别名docker network create mynet docker run -d --network mynet --network-alias db --network-alias database mysql:8.0这样其他容器可以通过db或database来访问这个MySQL容器。网络插件Docker支持第三方网络插件比如Weave# 安装Weavesudocurl-L git.io/weave -o /usr/local/bin/weavesudochmodax /usr/local/bin/weave# 启动Weaveweave launcheval$(weaveenv)# 运行容器docker run -d --name web nginx:latestCalico# 下载Calicocurl-O -L https://github.com/projectcalico/calicoctl/releases/download/v3.24.0/calicoctlchmodx calicoctl# 配置网络策略calicoctl apply -f network-policy.yaml这些插件提供了更高级的网络功能比如网络策略、跨数据中心网络等。Docker存储驱动Docker支持多种存储驱动不同的驱动有不同的特点查看当前存储驱动docker info|grepStorage Driver常见存储驱动overlay2推荐性能好功能完整支持所有Docker功能大部分Linux发行版的默认选择aufs老的存储驱动在一些老系统上还在用性能不如overlay2devicemapper使用块设备适合企业级存储配置复杂btrfs支持快照和子卷适合需要高级存储功能的场景配置存储驱动编辑/etc/docker/daemon.json{storage-driver:overlay2,storage-opts:[overlay2.override_kernel_checktrue]}然后重启Docker服务。Docker安全最佳实践安全是生产环境必须考虑的问题Docker提供了很多安全功能。用户命名空间默认情况下容器内的root用户就是宿主机的root用户这很危险。用户命名空间可以把容器内的root映射到宿主机的普通用户# 配置用户命名空间echodockremap:165536:65536/etc/subuidechodockremap:165536:65536/etc/subgid# 修改Docker配置echo{userns-remap: default}/etc/docker/daemon.json systemctl restart docker限制容器资源防止容器消耗过多资源# 限制内存和CPUdocker run -d --memory512m --cpus1.0nginx:latest# 限制磁盘IOdocker run -d --device-read-bps /dev/sda:1mb --device-write-bps /dev/sda:1mb nginx:latest使用非特权容器# 以非特权用户运行docker run -d --user1000:1000 nginx:latest# 禁用特权模式docker run -d --security-opt no-new-privileges nginx:latestAppArmor和SELinux如果系统支持可以使用AppArmor或SELinux加强安全# 使用AppArmor配置文件docker run -d --security-opt apparmor:docker-default nginx:latest# 使用SELinux标签docker run -d --security-opt label:type:container_t nginx:latest扫描镜像漏洞定期扫描镜像发现安全漏洞# 使用Docker官方扫描工具docker scan nginx:latest# 使用Clair扫描器docker run -d --name clair-db postgres:latest docker run -d --name clair --link clair-db:postgres quay.io/coreos/clair:latest签名和验证镜像使用Docker Content Trust验证镜像# 启用内容信任exportDOCKER_CONTENT_TRUST1# 推送签名镜像docker push myregistry.com/myimage:latest# 拉取时自动验证docker pull myregistry.com/myimage:latestDocker Registry私有仓库在企业环境中通常需要搭建私有镜像仓库。搭建简单的Registry# 运行Registry容器docker run -d\-p5000:5000\--restartalways\--name registry\-v registry-data:/var/lib/registry\registry:2# 推送镜像到私有仓库docker tag myapp:latest localhost:5000/myapp:latest docker push localhost:5000/myapp:latest# 从私有仓库拉取docker pull localhost:5000/myapp:latest配置HTTPS和认证生产环境的Registry需要HTTPS和认证# 生成证书mkdircerts openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days365-out certs/domain.crt# 生成认证文件mkdirauth docker run --entrypoint htpasswd registry:2 -Bbn admin passwordauth/htpasswd# 运行带认证的Registrydocker run -d\-p443:5000\--restartalways\--name secure-registry\-v$(pwd)/certs:/certs\-v$(pwd)/auth:/auth\-eREGISTRY_HTTP_TLS_CERTIFICATE/certs/domain.crt\-eREGISTRY_HTTP_TLS_PRIVATE_KEY/certs/domain.key\-eREGISTRY_AUTHhtpasswd\-eREGISTRY_AUTH_HTPASSWD_PATH/auth/htpasswd\-eREGISTRY_AUTH_HTPASSWD_REALMRegistry Realm\registry:2# 登录私有仓库docker login myregistry.comHarbor企业级仓库Harbor是VMware开源的企业级Docker仓库# 下载Harborwgethttps://github.com/goharbor/harbor/releases/download/v2.8.0/harbor-offline-installer-v2.8.0.tgztarxvf harbor-offline-installer-v2.8.0.tgz# 配置Harborcdharborcpharbor.yml.tmpl harbor.ymlvimharbor.yml# 修改配置# 安装Harborsudo./install.shHarbor提供了Web界面、用户管理、项目管理、漏洞扫描等企业级功能。Docker多架构镜像现在有越来越多的ARM服务器多架构镜像变得重要了。构建多架构镜像# 创建builder实例docker buildx create --name mybuilder --use docker buildx inspect --bootstrap# 构建多架构镜像docker buildx build\--platform linux/amd64,linux/arm64,linux/arm/v7\-t myapp:latest\--push.使用manifest# 创建manifestdocker manifest create myapp:latest\myapp:amd64\myapp:arm64\myapp:armv7# 推送manifestdocker manifest push myapp:latest在Dockerfile中处理架构差异FROM --platform$BUILDPLATFORM golang:1.19 AS builder ARG TARGETPLATFORM ARG BUILDPLATFORM ARG TARGETOS ARG TARGETARCH WORKDIR /app COPY . . RUN GOOS$TARGETOS GOARCH$TARGETARCH go build -o myapp FROM alpine:latest RUN apk --no-cache add ca-certificates COPY --frombuilder /app/myapp /usr/local/bin/ CMD [myapp]Docker和Kubernetes集成虽然Kubernetes现在支持多种容器运行时但Docker仍然是最常用的。准备镜像给Kubernetes使用# 使用非root用户 FROM node:16-alpine RUN addgroup -g 1001 -S nodejs RUN adduser -S nextjs -u 1001 WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction COPY . . RUN chown -R nextjs:nodejs /app USER nextjs EXPOSE 3000 CMD [node, server.js]Kubernetes部署文件apiVersion:apps/v1kind:Deploymentmetadata:name:myappspec:replicas:3selector:matchLabels:app:myapptemplate:metadata:labels:app:myappspec:containers:-name:myappimage:myregistry.com/myapp:v1.0ports:-containerPort:3000env:-name:NODE_ENVvalue:productionresources:limits:memory:512Micpu:500mrequests:memory:256Micpu:250mlivenessProbe:httpGet:path:/healthport:3000initialDelaySeconds:30periodSeconds:10readinessProbe:httpGet:path:/readyport:3000initialDelaySeconds:5periodSeconds:5镜像拉取策略spec:containers:-name:myappimage:myapp:latestimagePullPolicy:Always# 总是拉取最新镜像# imagePullPolicy: IfNotPresent # 本地没有才拉取# imagePullPolicy: Never # 从不拉取只用本地镜像容器监控和日志生产环境中监控和日志收集很重要。Prometheus监控version:3.8services:app:build:.ports:-3000:3000labels:-prometheus.io/scrapetrue-prometheus.io/port3000-prometheus.io/path/metricsprometheus:image:prom/prometheus:latestports:-9090:9090volumes:-./prometheus.yml:/etc/prometheus/prometheus.yml-/var/run/docker.sock:/var/run/docker.sock:rocommand:---config.file/etc/prometheus/prometheus.yml---storage.tsdb.path/prometheus---web.console.libraries/etc/prometheus/console_libraries---web.console.templates/etc/prometheus/consolesgrafana:image:grafana/grafana:latestports:-3001:3000environment:-GF_SECURITY_ADMIN_PASSWORDadminvolumes:-grafana-data:/var/lib/grafanavolumes:grafana-data:ELK日志收集version:3.8services:elasticsearch:image:docker.elastic.co/elasticsearch/elasticsearch:8.5.0environment:-discovery.typesingle-node-xpack.security.enabledfalseports:-9200:9200volumes:-es-data:/usr/share/elasticsearch/datalogstash:image:docker.elastic.co/logstash/logstash:8.5.0volumes:-./logstash.conf:/usr/share/logstash/pipeline/logstash.confdepends_on:-elasticsearchkibana:image:docker.elastic.co/kibana/kibana:8.5.0ports:-5601:5601environment:-ELASTICSEARCH_HOSTShttp://elasticsearch:9200depends_on:-elasticsearchapp:build:.logging:driver:gelfoptions:gelf-address:udp://localhost:12201tag:myappvolumes:es-data:使用Fluentd收集日志version:3.8services:fluentd:image:fluent/fluentd:v1.14-1ports:-24224:24224-24224:24224/udpvolumes:-./fluentd.conf:/fluentd/etc/fluent.confenvironment:-FLUENTD_CONFfluent.confapp:build:.logging:driver:fluentdoptions:fluentd-address:localhost:24224tag:docker.myappDocker性能调优容器资源限制合理设置资源限制避免容器消耗过多资源# 内存限制docker run -d --memory1g --memory-swap2g nginx:latest# CPU限制docker run -d --cpus1.5nginx:latest docker run -d --cpu-shares512nginx:latest# 磁盘IO限制docker run -d --device-read-bps /dev/sda:1mb nginx:latest docker run -d --device-write-bps /dev/sda:1mb nginx:latest优化Docker daemon编辑/etc/docker/daemon.json{log-driver:json-file,log-opts:{max-size:10m,max-file:3},storage-driver:overlay2,storage-opts:[overlay2.override_kernel_checktrue],default-ulimits:{nofile:{name:nofile,hard:65536,soft:65536}},max-concurrent-downloads:10,max-concurrent-uploads:5}容器启动优化# 使用多阶段构建减少镜像大小 FROM node:16-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction npm cache clean --force FROM node:16-alpine RUN apk --no-cache add dumb-init WORKDIR /app COPY --frombuilder /app/node_modules ./node_modules COPY . . USER node ENTRYPOINT [dumb-init, --] CMD [node, server.js]使用dumb-init作为PID 1进程处理僵尸进程和信号转发。故障排查和调试技巧容器无法启动# 查看容器日志docker logs container_name docker logs --details container_name# 查看容器事件docker events --filtercontainercontainer_name# 进入容器调试如果容器还在运行dockerexec-it container_name /bin/bash# 如果容器已经退出用同样的镜像启动一个临时容器docker run -it --rm --entrypoint /bin/bash image_name网络问题排查# 查看容器网络配置docker inspect container_name|jq.[0].NetworkSettings# 测试网络连通性dockerexeccontainer_namepinggoogle.com dockerexeccontainer_namenslookupgoogle.com dockerexeccontainer_name telnet another_container3306# 查看端口监听情况dockerexeccontainer_namenetstat-tulpn dockerexeccontainer_name ss -tulpn性能问题排查# 查看容器资源使用docker stats container_name# 查看容器进程dockerexeccontainer_namepsaux dockerexeccontainer_nametop# 查看系统调用dockerexeccontainer_namestrace-p1# 查看文件系统使用dockerexeccontainer_namedf-h dockerexeccontainer_namedu-sh /*使用dive分析镜像dive是一个很好用的镜像分析工具# 安装divewgethttps://github.com/wagoodman/dive/releases/download/v0.10.0/dive_0.10.0_linux_amd64.debsudoaptinstall./dive_0.10.0_linux_amd64.deb# 分析镜像dive myapp:latestdive可以显示镜像的每一层帮助优化镜像大小。总结Docker确实是个好东西能解决很多实际问题。从开发环境的统一到生产部署的简化再到微服务架构的实现都离不开容器技术。这篇文章涵盖了Docker的方方面面从基础概念到高级应用从网络配置到安全实践。特别是网络部分我花了很多篇幅来讲解因为这确实是很多人觉得困难的地方。网络是Docker中比较复杂的部分但一旦理解了原理用起来就得心应手了。记住几个要点默认bridge网络适合简单场景自定义网络支持服务发现更适合多容器应用生产环境要考虑网络安全和隔离跨主机网络需要用overlay或第三方插件不过也要理性看待Docker不是银弹不能解决所有问题。有些场景下传统的部署方式可能更简单直接。关键是要根据实际需求选择合适的技术。我自己用Docker这几年最大的感受就是它让部署变得可预测了。以前部署应用总是提心吊胆生怕环境不一致出问题。现在有了Docker本地测试通过的应用到生产环境基本不会有环境问题。当然Docker的学习曲线还是有的特别是网络和存储这块。但一旦掌握了效率提升还是很明显的。建议大家从简单的应用开始慢慢积累经验。最后技术是为业务服务的不要为了用Docker而用Docker。如果现有的部署方式已经很成熟没必要强行迁移。但如果遇到了环境不一致、部署复杂等问题Docker确实是个不错的选择。希望这篇文章对大家有帮助如果觉得有用的话别忘了点赞转发。有问题也欢迎留言讨论大家一起学习进步。关注运维躬行录我会持续分享更多实用的运维技术和经验让我们一起在运维的路上走得更远公众号运维躬行录个人博客躬行笔记

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询