发布时间: 更新时间:

docker

安装docker

#更新apt包索引
 sudo apt-get update

#安装包以允许apt通过 HTTPS 使用存储库
 sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
    
#添加Docker官方的GPG密钥
 curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

#设置稳定存储库
 echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  
#安装最新版本的Docker Engine和containerd
 sudo apt-get update
 sudo apt-get install docker-ce docker-ce-cli containerd.io
 
#hello-world 映像验证
 sudo docker run hello-world
# 使用脚本安装
 curl -fsSL https://get.docker.com -o get-docker.sh
 sudo sh get-docker.sh

Dockerfile

“点击展开go语言示例”

# 这个参考示例来自李文周大佬的bluebell项目

FROM golang:alpine AS builder

# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

# 移动到工作目录:/build
WORKDIR /build

# 复制项目中的 go.mod 和 go.sum文件并下载依赖信息
COPY go.mod .
COPY go.sum .
RUN go mod download

# 将代码复制到容器中
COPY . .

# 将我们的代码编译成二进制可执行文件 bluebell_app
RUN go build -o bluebell_app .

###################
# 接下来创建一个小镜像
###################
FROM debian:stretch-slim

COPY ./wait-for.sh /
COPY ./templates /templates
COPY ./static /static
COPY ./conf /conf

# 从builder镜像中把/dist/app 拷贝到当前目录
COPY --from=builder /build/bluebell_app /

RUN set -eux; \
	apt-get update; \
	apt-get install -y \
		--no-install-recommends \
		netcat; \
        chmod 755 wait-for.sh

# 声明服务端口
EXPOSE 8084

# 需要运行的命令
#ENTRYPOINT ["/bluebell_app", "conf/config.yaml"]

基础知识参考

  1. 卷(volumes):卷是由 Docker 管理的持久化数据(独立于容器的数据)。存储在由 Docker管理的主机文件系统(在 Linux 上的/var/lib/docker/volumes/ )。
# 将当前目录的相对路径挂载到/app目录中
     volumes:
       - ./:/app
  1. 镜像 (Image) :一个只读的模板(静态模板),包含了运行应用程序所需的所有代码、库、环境变量和配置文件。

  2. 容器 (Container):镜像的运行实例(运行环境)。基于镜像,在顶部增加了一个读写层。

docker compose

安装docker compose

# 单独下载和安装 Compose(不装Docker CLI)
# 下载 Docker Compose 的当前稳定版本
curl -SL https://github.com/docker/compose/releases/download/v2.7.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
 
# 对二进制文件应用可执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 测试安装
docker compose version

# 测试是否安装了旧版 v1
docker-compose version
# 如果输出v1则卸载,注意修改版本
sudo rm /usr/local/bin/docker-compose
# 脚本
curl -fsSL https://get.docker.com -o get-docker.sh && \
sudo sh get-docker.sh && \
docker -v && \
curl -SL https://github.com/docker/compose/releases/download/v2.7.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose && \
sudo chmod +x /usr/local/bin/docker-compose  && \
docker compose version

docker-compose.yaml

“点击展开和折叠代码”

version: '3.7'
services:

  mysql5.7:
    # 镜像名
    image: 'mysql:5.7'
    # 容器名(以后的控制都通过这个)
    container_name: mysql5.7
    # 重启策略
    restart: always
    environment:
      # 时区上海
      TZ: Asia/Shanghai
      # root 密码
      MYSQL_ROOT_PASSWORD: root
      # 初始化数据库(后续的初始化sql会在这个库执行)
      MYSQL_DATABASE: nacos_config
      # 初始化用户(不能是root 会报错, 后续需要给新用户赋予权限)
      MYSQL_USER: nacos
      # 用户密码
      MYSQL_PASSWORD: nacos
      # 映射端口
    ports:
      - 3306:3306
    volumes:
      # 数据挂载
      #- /root/mysql/data/:/var/lib/mysql/
      # 配置挂载
      #- /root/mysql/conf/:/etc/mysql/conf.d/
      # 初始化目录挂载,注意此处我只跑了这个挂载,只是为了说明其他配置不应该数据初始化
      - /root/mysql/init/:/docker-entrypoint-initdb.d/
    command:
      # 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配)
      --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
      --explicit_defaults_for_timestamp=true
      --lower_case_table_names=1
    networks:
      - proxy
      
  server:
    image: ghcr.io/USERNAME/server:master
    container_name: server
    ports:
      - 8082:8082
    expose:
      - "8082"
    depends_on:
      - mysql5.7
    restart: always
    volumes:
      - './data:/data/'
    networks:
      - proxy

  web:
    image: ghcr.io/USERNAME/web:master
    container_name: web
    depends_on:
      - server
    restart: always
    ports:
      - 3000:3000
    expose:
      - "3000"
    environment:
      - VIRTUAL_HOST=example.com
      - VIRTUAL_PORT=3000
      - LETSENCRYPT_HOST=example.com
      - [email protected]
    networks:
      - proxy

networks:
  proxy:
    name: nginx-proxy
    external: true

“点击展开nginx-proxy代码”

version: '3'

services:

  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - conf:/etc/nginx/conf.d
      - vhost:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
      - dhparam:/etc/nginx/dhparam
      - certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
    restart: always
    networks:
      - nginxproxy
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: nginx-proxy-le
    depends_on:
      - nginx-proxy
    volumes:
      - vhost:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
      - dhparam:/etc/nginx/dhparam:ro
      - certs:/etc/nginx/certs
      - acme:/etc/acme.sh
      - /var/run/docker.sock:/var/run/docker.sock:ro
    ##################
    # 由于LETSENCRYPT证书速率限制,可使用ZeroSSL
    # 注释掉web服务environment中的:
      - LETSENCRYPT_HOST=example.com
      - [email protected]
    # 需添加如下environment
    environment:
      - ACME_CA_URI=https://acme.zerossl.com/v2/DV90
      - ZEROSSL_API_KEY=
    ##################
    restart: always
    networks:
      - nginxproxy
      
volumes:
  conf:
  vhost:
  html:
  dhparam:
  certs:
  acme:

networks:
  nginxproxy:
    name: nginx-proxy
    external: true

基础知识参考

以下简介节选自docker compose文档

  1. Compose 中的网络:

Compose默认为您的应用程序设置单个网络。服务中的每个容器都加入默认网络。例如,假设您的应用程序是在一个名为myapp的目录,运行docker-compose up时会创建一个名为myapp_default的网络,服务中使用web和db的配置创建的容器会以web和db的名字加入myapp_default。

但是,当你使用external(外部网络,例如你有2个或多个docker-compose.yml)时,Compose不会创建默认网络,你必须使用docker network create Your_Nerwork预先创建网络。

注意:文档中示例写法过时,会报错

networks:
  proxy:
    external:
      name: nginx-proxy

应写为:

networks:
  proxy:
    name: nginx-proxy
    external: true

常用命令

Docker命令

docker run [参数] imagename              # 新建并启动容器    
  --name = "name" 容器取名
  -it 交互模式进入容器
  -d 后台启动容器 注意:一般后台启动要有前台的应用,否则很可能被守护程序杀掉
  -p ip:主机端口:容器端口 #指定端口映射
  -v或--volume /卷名称的路径:/容器中的挂载路径

镜像:
docker search [image]                         # 搜索dockerhub的镜像
docker images -a/-q                         # 列出本地主机的镜像
    -a 显示所有信息
    -q 显示所有id
docker build -t [tag] .                     # 构建标签为tag的镜像
docker pull [镜像:版本号]                   # 拉取镜像    
docker rmi -f [image]                         # 删除单个镜像
docker rmi -f $(docker images -aq)          # 删除所有镜像    

容器:
docker ps -a/-q                             # 显示当前正在运行的容器
  -a 显示当前运行的容器,并显示历史运行过的容器
  -q 只显示运行容器的编号
docker logs [容器id]                         # 日志     
docker top [容器id]                          # 查看容器中进程信息
docker inspect [容器id]                      # 查看容器的详细信息
docker start [容器id]                        # 启动容器
docker restart [容器id]                      # 重启容器
docker stop [容器id]                         # 停止容器
docker kill [容器id]                         # 强制停止容器
docker stop $(docker ps -a -q)              # 停止所有容器
docker rm [容器id]                           # 删除停止状态的容器
docker rm -f [容器id]                        # 强制删除容器
docker rm $(docker ps -a -q)                # 删除所有容器
docker network rm $(docker network ls -q)   # 删除所有network
exit 容器停止并退出
ctrl+p+q 容器不停止退出
docker exec -it mysql /bin/bash             # 进入正在执行的mysql容器
docker exec -it 容器名 /bin/sh              # 进入容器
docker exec -it 容器名 -c "apt-get update && apt-get install -y vim"    # 进入容器安装vim编辑器
docker exec -it 容器名 -c " apk add --update vim"    # 进入alpine容器安装vim编辑器
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [container_name_or_id]             # 查看容器ip
docker cp [容器id: 路径]  [主机目的路径] # 从容器拷贝内容到主机(容器关闭状态,不必进入容器)

卷:
docker volume ls                            # 列出所有卷
docker volume rm [volume]                   # 删除卷(持久化数据)
docker system prune --all --force --volumes # 删除一切(容器、卷)
Docker compose命令

docker compose up --build                   # (重新)构建,然后启动容器
docker compose up -d                        # 在后台启动服务
docker compose pull                         # 拉取
    docker compose -f docker-compose.yml up -d  # 启动指定docker-compose.yml
    docker compose -f docker-compose.yml pull   # 拉取指定docker-compose.yml

查看:
docker compose ps                           # 查看正在运行中的容器
docker compose ps -a                        # 查看所有编排容器,包括已停止的容器
docker compose images                       # 列出Compose文件构建的镜像
docker compose logs                         # 查看日志
docker compose logs [serviceName]           # 查看某服务的日志 
docker compose logs -f [serviceName]        # 查看某服务的实时日志

操作:
docker compose stop                         # 停止服务
docker compose start                        # 启动已经存在的服务
docker compose pause [serviceName]          # 暂停服务
docker compose unpause [serviceName]        # 恢复服务
docker compose restart [serviceName]        # 重启服务
docker compose rm                           # 删除所有(停止状态的)服务容器
docker compose down                         # 删除所有容器
docker compose down --remove-orphans        # 删除孤立容器


docker compose config  -q    # 验证(docker-compose.yml)文件配置,当配置正确时,不输出任何内容
docker compose exec --index=1 [serviceName] sh     # 进入某服务的第1个容器执行命令

docker compose --help                       # 帮助

actions自动化部署前后端分离项目

参考文章

本文使用github actions + docker compose部署到github container registry(适用于中小型项目) 附:容器注册平台对比

  1. 准备好你的dockerfile

  2. 使用github actions

    “点击展开示例actions”

    on:
      push:
        branches:
          - master
          
      workflow_dispatch:
    
    env:
      REGISTRY: ghcr.io
      IMAGE_NAME: ${{ github.repository }}
    
    jobs:
              
      build-and-push-image:
        runs-on: ubuntu-latest
        permissions:
          contents: read
          packages: write
        strategy:
          matrix:
            node: [ '14' ]    
    
        steps:
          - name: Checkout repository
            uses: actions/checkout@v2
    
          - name: Setup node
            uses: actions/setup-node@v2
            with:
              node-version: ${{ matrix.node }}
              
          - name: npm install
            run: |
              cd web                       #进入前端dockerfile目录
              npm install       
                  
          - name: Set up QEMU
            uses: docker/setup-qemu-action@v1
          
          - uses: docker/setup-buildx-action@v1
            id: builder1
          
          - uses: docker/setup-buildx-action@v1
            id: builder2
            
          - name: Log in to the Container registry
            uses: docker/login-action@v1
            with:
              registry: ${{ env.REGISTRY }}
              username: ${{ github.actor }}
              password: ${{ secrets.GITHUB_TOKEN }}
              
          # 用于消毒标签,tag是此动作的重要功能之一,本示例没使用,请见文档    
          - name: Extract metadata (tags, labels) for Docker
            id: meta1
            uses: docker/metadata-action@v3
            with:
              images: ghcr.io/username/server      # images地址
          - name: Extract metadata (tags, labels) for Docker
            id: meta2
            uses: docker/metadata-action@v3
            with:
              images: ghcr.io/username/web         # images地址
    
    
          - name: Build and push Docker image 1
            uses: docker/build-push-action@v2
            with:
              builder: ${{ steps.builder1.outputs.name }}        
              context: ./server                # 服务端dockerfile目录
              file: ./server/Dockerfile        # 服务端dockerfile
              push: true
              tags: ${{ steps.meta1.outputs.tags }}
              labels: ${{ steps.meta1.outputs.labels }}
              cache-from: type=gha
              cache-to: type=gha,mode=max
    
          - name: Build and push Docker image 2
            uses: docker/build-push-action@v2
            with:
              builder: ${{ steps.builder2.outputs.name }}        
              context: ./web                  # 前端dockerfile目录
              file: ./web/Dockerfile          # 前端dockerfile
              push: true
              tags: ${{ steps.meta2.outputs.tags }}
              labels: ${{ steps.meta2.outputs.labels }}
              cache-from: type=gha
              cache-to: type=gha,mode=max
      deploy:
        runs-on: ubuntu-latest
        needs: build-and-push-image
        steps:
                  
          - uses: appleboy/ssh-action@master
            with:
              host: ${{ secrets.host }}          #仓库设置中添加Secrets:HOST
              username: root
              password: ${{ secrets.PASSWORD }}  #仓库设置中添加Secrets:PASSWORD
              port: 22
              script: |         
                echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin     # 用户名
                docker compose -f docker-compose-nginx.yaml -f docker-compose-app.yaml pull   # docker-compose名
                docker compose -f docker-compose-nginx.yaml -f docker-compose-app.yaml up -d   # docker-compose名
    
    # 此actions许多参数由github自动提供,无需添加,需修改的均已注释
    

  3. 在服务器上完成向 Container registry 验证

具体操作:打开/etc/profile

export CR_PAT=YOUR_TOKEN
source /etc/profile
echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
  1. 新建docker-compose-app.yaml和代理容器docker-compose-nginx.yaml,示例文档。如有不懂,请查看acme-companion和示例文档。最后,Issues中的实例可能会有帮助。
Licensed under CC BY-NC-SA 4.0
最后更新于 2022-07-25