Docker极简入门
本文介绍了Docker的基本概念、命令和使用方法。
环境说明
| 软件 | 版本 | 说明 |
|---|---|---|
| macOS Monterey | 12.0.1 | |
| Docker | 20.10.8 | |
通过docker load -i ocr_service.tar方式加载的image,会出现运行不了打包的python的情况,提示Illegal instruction,表示CPU类型不同。还是得运行在匹配的系统里才行。
Docker国内镜像
/etc/docker/daemon.json
{
"builder":
{
"gc":
{
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"debug": true,
"experimental": false,
"registry-mirrors":
[
"https://dockerpull.pw",
"https://dockerhub.icu",
"https://hub.rat.dev",
"https://register.librax.org",
"https://docker-0.unsee.tech",
"https://docker-cf.registry.cyou",
"https://docker.1panel.live",
"https://docker.m.daocloud.io",
"https://dhub.kubesre.xyz",
],
"dns":
[
"8.8.8.8",
"114.114.114.114"
]
}
Docker的安装
Centos7
su - root
yum install -y yum-utils device-mapper-persistent-data lvm2
#从阿里云服务器访问不了download.docker.com
#registry-1.docker.io 也是访问不了
#yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
#yum install -y docker-ce docker-ce-cli containerd.io
yum install -y docker
systemctl start docker
systemctl enable docker
#docker-ce的安装
#https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.57e31b11L5nmE3
yum install -y yum-utils
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl start docker
systemctl enable docker
#有时containerd不支关闭,需要手工关闭
#systemctl stop containerd
阿里云镜像加速获取自己的镜像地址
dnf -y install dnf-plugins-core
dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl enable --now docker
# docker run hello-world
Docker基本结构
Docker命令分类
Docker命令介绍
获取命令帮助
docker [COMMAND] --help
容器生命周期管理
- docker run
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
docker run -d --restart always your-image-name 自动重启参数
该命令从IMAGE创建一个新容器。如果不指定--name参数,每次运行此命令都生成一个实例并随机分配一个容器ID。
举例
docker run --name smy-haproxy -d -p 80:80 smy-haproxy
run命令常用参数解释
-i -t 指定为交互模式和分配伪终端,常常一起出现,
如docker run -it ubuntu echo /etc/hosts
--name 指定容器实例ID名称
-v [host-dir]:[container-dir]:[rw|ro] 挂载本地文件到容器中
#run -v /Users/name/books:/books --name smy-nginx -t -i nginx /bin/bash
-p [host-port]:[container-port] 将容器端口映射给宿主主机端口
-e VARNAME=VARVALUE 设置环境变量
--link name:alias 创建指向另外一个容器的连接名称
# docker run --name smy-haproxy --link smy-web1:web1 --link smy-web2:web2 -d -p 80:80 smy-haproxy
--rm The container will be automatically removed when it stops
-w /work/dir/ 工作目录,指定在容器运行时,命令执行时所在的目录
--restart always 自动重启
#或者在compose.yaml服务下面添加 restart: always
检查当前启动模式 docker inspect --format='{{.HostConfig.RestartPolicy.Name}}' <container_name_or_id>
docker run -d --restart always -p 6385:6385 --name smy-develop-smy-redis smy-develop-smy-redis
复制文件
docker cp smy-php-fpm:/usr/local/etc/php-fpm.d/www.conf /tmp/
- docker start/stop/restart 启动容器
docker start/stop/restart CONTAINER_ID
start常用参数
-i 交互模式,挂载标准输入 interactive
-a 挂载标准错误/标准输出
- docker exec 对已存在容器执行命令
docker exec CONTAINER_ID
举例
docker exec -it CONTAINER_ID /bin/sh
Image管理
查看image
docker image ls
一些镜像仓库服务 Image Registry
- Docker Hub: https://hub.docker.com/
- Amazon Elastic Container Registry (ECR): https://aws.amazon.com/ecr/
- Google Container Registry (GCR): https://cloud.google.com/container-registry
- Microsoft Azure Container Registry (ACR): https://azure.microsoft.com/en-us/services/container-registry/
- Harbor: https://goharbor.io/
- Quay.io: https://quay.io/
拉取镜像语法
docker image pull <repository>:<tag>
latest tag并不一定表示最新版本
没有tag的镜像是dangling悬虚镜像
如
docker image pull alpine:latest
docker image pull microsoft/dotnet:latest
docker image pull gcr.io/nigelpoulton/tu-demo:v2
登录docker hub
官方镜像仓库
docker login -u swingcoder
dckr_pat_V4w_zdsHZqN0aQ4KlalxZGmGmng
构建多平台镜像
docker buildx build --platform linux/amd64,linux/arm64 -t semantic-api:v1 --load .
#如果发现错,可以先清一下缓存
docker builder prune
#创建新的buildkit
docker buildx create --use
查看文件对多平台的支持情况
docker buildx imagetools inspect python:3.8-slim
拉取特定平台的文件
docker pull python:3.8-slim@sha256:1d52838af602b4b5a831beb13a0e4d073280665ea7be7f69ce2382f29c5a613f # 拉取 linux/amd64 平台的镜像
docker pull python:3.8-slim@sha256:def456 # 拉取 linux/arm64 平台的镜像
然后在官网下载 https://pypi.org/project/numpy/1.24.4/#files,修改包名和版本号,找到对应的built分发包,搜索manylinux,x86_64位的适用Linux,cpython 3.8(看安装的python版本号,找对应的版本) 打包的。
容器运维操作
- docker attach
docker attach CONTAINER_ID
- docker inspect
- docker ps 查看容器
-a 显示所有容器
-l 显示最后运行的容器
-n Num 显示最后Num条容器
- docker commit 临时保存容器的修改内容
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
commit只能保存正在运行的容器内容。而且这个保存数据是临时的,不会因为重启容器失效,如果要永久保存为IMAGE,推荐使用docker build方式构建。
- docker history IMAGE
- docker logs CONTAINER
- docker events
镜像仓库命令
- docker pull 拉取一个镜像包
docker pull [OPTION] [REMOTE_HOST:REMOTE_PORT/][REGISTRY/]NAME[:TAG @DIGEST]
- docker push 将本地image或repository推送到镜像库
docker push [OPTION] NAME[:TAG]
- docker images 列出本地images
docker images [OPTIONS] [REPOSITORY[:TAG]]
- docker rmi 删除本地image镜像
docker rmi [OPTIONS] IMAGE [IMAGE...]
- docker rm 删除本地容器
docker rm [OPTIONS] CONTAINER [CONTAINER...]
删除一些没有标签的image,通常为build时的中间产物
docker images -f "dangling=true"
docker rmi $(docker images -f "dangling=true" -q)
Dockerfile指令
完整指令 https://docs.docker.com/reference/dockerfile/
ADD:复制本地文件或目录到镜像,可以复制远程文件和自动解压缩。类似的有COPY
ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
COPY:复制本地文件或目录到镜像。不支持远程和自动解压。
CMD:作为容器启动默认执行的命令。如果有多个CMD只有最后一个生效,同时会覆盖FROM继承的父镜像里的CMD指令。
Docker应用栈
Docker的理论是一个容器运行一个进程,多个容器组成应用栈(集群)。
同一个应用栈的docker应用会创建相同的局域网IP,通过--link可以定义连接的主机名称,这样在同一个集群的应用内部可以通过主机名称进行通讯。
下面的例子构造一个网站的基础架构
因为一个网站需要使用多个应用,我们要保证他们在同一个局域网且能互相通讯,所以先创建一个新的局域网(--network与--link不能同时使用,使用--link才会自动创建hosts名称)
docker network create app-tier --driver bridge
- mysql
docker run --name smy-mysql --network app-tier -d -p 33070:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.6.48php-fpm
redis生成自定义镜像Dockerfile
FROM redis:latest
COPY redis.conf /usr/local/etc/redis/redis.conf
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
docker build -t smy-redis .
docker run --name smy-redis --network app-tier -d -v /Users/zhugan/Work/code/docker/redis/redis.conf:/etc/redis/redis.conf smy-redis
- php-fpm
安装官方php,不要安装非官方版本(搜索php,从tag里找php版本)。
docker pull php:7.3.32-fpm
构造php-fpm自定义镜像
Dockerfile
FROM php:7.3.32-fpm
RUN apt-get update && \
pecl channel-update pecl.php.net && \
pecl bundle redis && cd redis && phpize && ./configure --disable-redis-igbinary && make && make install && \
docker-php-ext-install pdo_mysql && \
docker-php-ext-enable opcache redis && \
docker-php-source delete && \
rm -r /tmp/* /var/cache/* /var/www/html/*
RUN echo '\
opcache.interned_strings_buffer=16\n\
opcache.load_comments=Off\n\
opcache.max_accelerated_files=16000\n\
opcache.save_comments=Off\n\
' >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
COPY php.ini /usr/local/etc/php/php.ini
生成新的php-fpm包
docker build -t smy-php-fpm .
Dockerfile of swoole version
FROM php:8.2-fpm
RUN apt-get update && \
docker-php-ext-install pdo_mysql && \
docker-php-ext-enable opcache redis swoole mcrypt
RUN echo '\
opcache.interned_strings_buffer=16\n\
opcache.load_comments=Off\n\
opcache.max_accelerated_files=16000\n\
opcache.save_comments=Off\n\
' >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
RUN apt-get install -y \
libfreetype-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg --with-png \
&& docker-php-ext-install -j$(nproc) gd
RUN rm -r /tmp/* /var/cache/* /var/www/html/*
COPY php.ini /usr/local/etc/php/php.ini
docker build -t swingcoder/smy-php-fpm:8.2 .
运行php-fpm
docker run --name smy-php-fpm --network app-tier -d -v /Users/zhugan/Work/code/projects/sanmaoyou/ss.sanmaoyou.com:/app/ss.sanmaoyou.com smy-php-fpm
要注意将nginx配置的root目录指向为/app/ss.sanmaoyou.com/public/,否则会出现Primary script unknown,或者绑定跟主机一样的目录,这样可不改nginx配置
参考:php-fpm安装扩展的方法
Installing PHP extensions from source in your Dockerfile – Olivier Laviale
- nginx
docker run --name smy-web1 --network app-tier -d -v /Users/zhugan/Work/code/docker/nginx/conf.d/ssdev.sanmaoyou.com.conf:/etc/nginx/conf.d/ssdev.sanmaoyou.com.conf:ro -v /Users/zhugan/Work/code/projects/sanmaoyou/ss.sanmaoyou.com:/app/ss.sanmaoyou.com --link smy-php-fpm:smy-php-fpm --link smy-mysql:smymysql --link smy-redis:smyredis nginxha-proxy
- haproxy
Dockerfile
FROM haproxy:latest
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
docker build -t smy-haproxy .
docker run --name smy-haproxy --network app-tier -d -v /Users/zhugan/Work/code/docker/haparoxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg --link smy-web1:web1 --link smy-web2:web2 -p 80:80 smy-haproxy# Docker镜像的构建
docker commit是将容器内容临时保存镜像,docker build是从配置文件构建镜像
从STDIN读入Dockerfile
docker build - < Dockerfile
从STDIN读入压缩的context
docker build - < context.tar.gz
从URL读取context
docker build github.com/creack/docker-firfox
从当前文件夹读取context
docker build -t apache .
指定Dockerfile路径和context路径
docker build -f /path/to/dockerfile /app/myapp
.dockerignore过滤构建的文件
Docker镜像的导入与导出
docker export用于持久化容器;docker push和docker save用于持久化镜像;docker import是迁移镜像的方法;docker save线下分发包。
docker save -o app-ocr_service.tar app-ocr_service
docker load -i
创建私有Registry服务器
安装registry插件
$ docker pull registry
启动服务
$ docker run -d -p 5000:5000 --restart always --name registry registry:2
自定义端口
docker run -d \
-e REGISTRY_HTTP_ADDR=0.0.0.0:5001 \
-p 5001:5001 \
--name registry-test \
registry:2
例子
$ docker pull ubuntu
$ docker tag ubuntu localhost:5000/ubuntu
$ docker push localhost:5000/ubuntu
停止registry
docker container stop registry
删除regisry
docker container stop registry && docker container rm -v registry
网络与通讯
docker的网络种类
共享主机网络 --network host
docker run --rm --network host <image_name>
仅支持主机为Linux,在macOS和windows运行的是虚拟主机,不支持此网络类型
格接网络 --network bridge
docker run --rm --network bridge <image_name>
#or
docker network create app-tier --driver bridge
docker run --rm --network app-tier <image_name>
会创建新的网段和网址与主机进行通讯
当使用桥接bridge网络类型时,在容器里有内部的域名host.docker.internal指向主机IP
分层网络 overlay
docker network create -d overlay my-overlay-network
docker service create --network my-overlay-network my-service
Docker Compose
参考手册 https://docs.docker.com/reference/compose-file/
组合各服务在一个配置里管理。
compose例子
一个compose.yaml例子
redis.yaml
services:
redis:
image: "redis:alpine"
compose.yaml
include:
- redis.yaml
services:
web:
build: .
ports:
- "8000:5000"
develop:
watch:
- action: sync
path: .
target: /code
build . 指令表示从当前目目读取Dockerfile生成image
develop 开发选项,watch表示监察path目录,文件有变动,自动同步到taget目录
include 引入其它配置文件
服务的简单例子
services:
web:
image: nginx:latest
ports:
- "8080:80"
db:
image: postgres:13
environment:
POSTGRES_USER: example
POSTGRES_DB: exampledb
绑定本地文件
services:
proxy:
image: nginx
volumes:
- type: bind
source: ./proxy/nginx.conf
target: /etc/nginx/conf.d/default.conf
read_only: true
ports:
- 80:80
depends_on:
- backend
backend:
build:
context: backend
target: builder
The backend service builds an image from the Dockerfile located in the backend directory that is set to build at stage builder更多compose.yaml配置例子,一些公开的配置不用自己从头开始弄,可以直接引用他人配置好的 https://github.com/docker/awesome-compose
相关CLI命令说明
#detach模式,即后台运行
docker compose up -d
#关闭
docker compose down
#查看log
docker compose logs
#查看进程
docker compose ps
#查看image
docker image ls
#watch模式
docker compose --watch
#查看正在运行的项目
docker compose ls
#重新构造项目
docker compose build
#启动与重建一起
docker compose up --build
全部命令帮助 https://docs.docker.com/reference/cli/docker/compose/
配置文件重要参数解释
depens_on定制service的启动顺序links定义一个指定其它service的容器的网络连接
web:
links:
- db
- db:database #service:alias
- redis
expose暴露端口
expose:
- "3000"
- "8000"
- "8080-8085/tcp"
secrets定义一些安全配置,顶级字段,可复用
services:
frontend:
image: example/webapp
secrets:
- server-certificate
secrets:
server-certificate:
file: ./server.cert
volumes 定义本地目录与容器目录映射关系,顶级字段
services:
backend:
image: example/backend
volumes:
- type: volume
source: db-data
target: /data
volume:
nocopy: true
subpath: sub
- type: bind
source: /var/run/postgres/postgres.sock
target: /var/run/postgres/postgres.sock
volumes:
db-data:
- secrets的配置
build构建配置
docker compose build
- docker-compose.yaml中定义的同名env变量,可以覆盖Dockerfile中的,实现运行时环境变量功能,如docker-compose.yaml
version: '3.8'
services:
myservice:
build: .
environment:
- MY_VARIABLE=override_value # Overrides the default value
- ANOTHER_VARIABLE=another_override_value # Overrides the default value
Dockerfile
FROM alpine:latest
# Set default environment variables
# 此默认值会被docker-compose.yaml中定义的覆盖
ENV MY_VARIABLE="default_value"
ENV ANOTHER_VARIABLE="another_default_value"
CMD ["echo", "MY_VARIABLE is $MY_VARIABLE"]
连接多个Docker服务
- 方案1:目标docker要安装
portainer/agent
docker run -d -p 9998:9001 --name portainer_agent --restart=always -v /var/run/docker.sock:/var/run/docker.sock portainer/agent
第一个PORT 9998是主机的,后一个9001是docker容器的
portainer默认只允许一台客户机连接,需要使用edge agent服务(要开启docker swarm init,未验证过)
docker run -d -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes -v portainer_agent_data:/data --restart always -e EDGE=1 -e EDGE_ID=<unique-id> -e EDGE_KEY=<unique-key> -e EDGE_INSECURE_POLL=1 --name portainer_edge_agent portainer/agent:latest
- 方案2:使用docker自带的context切换功能
docker context create my-remote-server --docker "host=ssh://username@remote-host"
docker context use my-remote-server
#电脑上默认用的名称叫 desktop-linux
一些问题
docker compose up --build
时报错
failed to authorize: failed to fetch oauth toke
需要设置环境变量
export DOCKER_BUILDKIT=0
export COMPOSE_DOCKER_CLI_BUILD=0
Docker 安装PHP扩展
docker-php-ext-install bcmatch zip
清理
查看空间使用情况
docker system df
清理所有停止的容器、未使用的网络、悬空镜像(即没有标签且未被任何容器引用的镜像)、缓存
docker system
只清理悬空镜像
docker image prune
清理构建缓存
docker builder prune