安装及升级 docker
RedHat/CentOS
安装仓库文件
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
安装 docker
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
升级 docker 版本
sudo yum update 'docker-ce*'
docker system
管理 docker 系统
# 检查 docker 占用的系统空间
docker system df
# 显示 docker 系统信息
docker system info
# 删除无用的容器,网络,镜像等
docker system prune
docker build
docker build -t image-name:tag /image/context/path
# 生成镜像到指定registry
docker build -t registry-host:port/image-name:tag /image/context/path
# 引用其它image:tag生成一个新image:tag
docker tag <source-image>[:tag] <new-image>[:tag]
docker image
docker images
docker images
# 列出所有无标签的镜像 (dangling)
docker images --filter 'dangling=true'
# 列出镜像名包含指定模式的镜像,例如镜像名为 'www.myregistry.net/app/web-service:1.0.3'
docker images --filter 'reference=*/*/web*'
docker images --filter 'reference=www.myregistry.net/*/*'
可以同时使用多个 --filter
参数进行筛选
docker image rm
docker rmi image-name
# 删除所有无标签(dangling)镜像
docker rmi $(docker images --filter 'dangling=true' -q)
docker image prune
# 删除所有无标签(dangling)镜像
docker image prune
# 删除所有无标签和不被任何容器引用的镜像
docker image prune -a
docker history
查看镜像的生成历史,层信息等
docker history image-name
docker login
docker login registry-url
docker pull registry-host:port/image-name:tag
docker push registry-host:port/image-name:tag
docker container
# 查看当前运行的容器
docker ps [-a]
# 运行容器, --rm 允许容器退出时自动删除该容器
docker run -it --rm [--name <container-name>] [-v <host-dir:container-dir>] [-p <host-port:container-port>] <image-name> [command]
# 后台运行容器
docker run -d --rm [--name <container-name>] <image-name> [command]
# 在指定容器内运行命令
docker exec <container-name> ls -l
# 以可交互方式进入容器
docker exec -it <container-name> bash
# 容器重命名
docker rename <container-name> <new-name>
# 停止所有正在运行的容器
docker stop $(docker ps -q)
# 删除所有停止的容器
docker rm $(docker ps --filter 'status=exited' -q)
# 删除指定名称的容器
docker rm $(docker ps --filter 'name=substr' -q)
# 删除所有镜像
docker rmi `docker images -q`
docker save & load
# 从容器生成镜像
docker commit <container-name> <image-name:tag>
# 将一或多个镜像保存到tar文件
docker save -o image.tar <image-name:tag>
# 从保存的tar文件恢复镜像
docker load -i image.tar
# 从容器中导出文件系统
docker export -o container-fs.tar <container-name>
# 将文件系统导入镜像中
docker import container-fs.tar <image-name:tag>
docker logs
# Follow log output
docker logs <container_name> -f
# Show timestamps
docker logs <container_name> -t
# Number of lines to show from the end of the logs
docker logs <container_name> --tail 10
# Show logs since timestamp (e.g. 2022-05-05T12:30:00Z) or relative (e.g. 1h30m for 1 hour and 30 minutes)
docker logs <container_name> --since 1h30m
docker logs <container_name> --since 2022-05-05T12:30:00Z
# Use multiple options
docker logs <container_name> -t -f --tail 50
docker network
docker 访问主机的 hostname
host.docker.internal
Prune unused Docker objects
- 清理 image 对象的无用数据
# Only cleans up dangling images. A dangling image is one that is not tagged
# and is not referenced by any container.
docker image prune
# To remove all images which are not used by existing containers
docker image prune -a
# Only remove images created more than 24 hours ago
docker image prune -a --filter "until=24h"
- 清理 container 对象的无用数据
# To remove stopped containers older that 24 hours
docker container prune -a --filter "until=24h"
- 清理 volume 对象的无用数据
# To remove volumes which are not labeled with the "keep" label
docker volume prune -a --filter "label!=keep"
- 清理 network 对象的无用数据
docker volume prune -a --filter "until=24h"
- 清理多种对象的无用数据
# This is a shortcut that prunes images, containers, and networks. Volumes are not pruned by default
docker system prune
# To also prune volumes
docker system prune --volumes
在 Container 中访问外部 Docker Daemon
以 Alpine 镜像为例,假设宿主机 Docker daemon 的套接字文件是 /var/run/docker.sock
docker run -it \
--rm \
--name alpine \
-e http_proxy=http://127.0.0.1:7890 \
-e https_proxy=http://127.0.0.1:7890 \
-v /var/run/docker.sock:/var/run/docker.sock \
alpine
apk add --no-cache docker-cli
Dockerfile
docker build
命令从 Dockerfile
和 context 构建镜像。构建使用的上下文是包含一组文件的 PATH
或 URL
。 PATH
是本地文件系统上的目录,URL
是一个 Git 仓库位置。
构建上下文会递归处理文件。所以 PATH
会包含所有子目录,URL
会包含所有 submodules。下面例子的构建命令使用当前目录 (.
) 作为构建上下文。
docker build .
Dockerfile
通常位于上下文的根目录中,但可以在 docker build
中使用 -f
标志来指向文件系统中任何位置的 Dockerfile。
docker build -f /path/to/a/Dockerfile .
也可以指定要生成镜像的 repository 和 tag
docker build -t shykes/myapp .
使用多个 -t
参数可以给镜像打不同的 tag 并生成到多个 repository
docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
SpringBoot Java App Dockerfile
FROM maven:3.8.6-openjdk-11-slim AS builder
LABEL maintainer="appuser@exmaple.com"
ARG MAVEN_OPTS
RUN mkdir /build
WORKDIR /build
COPY pom.xml $HOME
RUN mvn verify --fail-never
COPY . /build
RUN mvn clean package -DskipTests
FROM adoptopenjdk/openjdk11:alpine-jre
LABEL maintainer="appuser@exmaple.com"
ARG BUILD_DATE
ARG BUILD_VERSION
ARG VCS_REF
LABEL org.label-schema.schema-version="1.0"
LABEL org.label-schema.build-date=$BUILD_DATE
LABEL org.label-schema.name="java-app"
LABEL org.label-schema.version=$BUILD_VERSION
LABEL org.label-schema.description="java app for test purpose."
LABEL org.label-schema.url="https://java-app.example.com"
LABEL org.label-schema.vcs-url="https://github.com/example/java-app.git"
LABEL org.label-schema.vcs-ref=$VCS_REF
LABEL org.label-schema.docker.cmd="docker run -d -e SPRING_PROFILES_ACTIVE=test -p 8900:8900 java-app"
RUN apk add --no-cache tini
RUN addgroup -S appuser && adduser -S -s /bin/false -G appuser appuser
RUN mkdir /app
WORKDIR /app
RUN chown -R appuser:appuser /app
COPY --chown=appuser:appuser --from=builder /build/target/java-app.jar /app
USER appuser
EXPOSE 8900
ENTRYPOINT ["tini --"]
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "java-app.jar"]
- 第一阶段构建时,Maven 需要通过代理下载依赖,可以设置
MAVEN_OPTS
环境变量 来向启动 Maven 的 JVM 传递代理设置。 - 第二阶段构建时,
apk
需要通过代理下载tini
工具,可以设置http_proxy
和https_proxy
环境变量来使用代理,因为这两个环境变量是 Dockerfile 的预定义 ARGs,所以不需要在 Dockerfile 中再使用ARG http_proxy
和ARG https_proxy
使用 Dockerfile 构建镜像,并使用 --build-arg
参数传递 ARG 环境变量
docker build --rm \
--build-arg BUILD_DATE=$(date -u -Is) \
--build-arg BUILD_VERSION=1.0.0 \
--build-arg VCS_REF=$(git rev-parse HEAD) \
--build-arg http_proxy=http://127.0.0.1:7890 \
--build-arg https_proxy=http://127.0.0.1:7890 \
--build-arg MAVEN_OPTS="-Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=7890 -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=7890" \
-t java-app .
启动 SpringBoot app 容器
docker run -it --name app-name -e SPRING_PROFILES_ACTIVE=test -p 8900:8900 java-app
docker-compose
安装 docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose 命令行
docker-compose 命令
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
Options:
-f, --file FILE Specify an alternate compose file
(default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name
(default: directory name)
--project-directory PATH Specify an alternate working directory
(default: the path of the Compose file)
Commands:
build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the Compose file
create Create services (deprecated)
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information
如果没有通过-f
指定docker-compose.yml
文件路径,Compose会搜索当前目录及其父目录来寻找docker-compose.yml
.
# 启动服务,-d 选项让服务后台运行(detach)
docker-compose up -d [SERVICE...]
# 停止容器并删除up命令创建的容器,网络
docker-compose down
# 列出容器
docker-compose ps [SERVICE...]
# 列出服务名
docker-compose ps --services
# 列出服务创建容器时要使用的镜像
docker-compose images [SERVICE...]
# 显示正在运行的进程
docker-compose top
# 构建或重新构建服务,默认镜像名为 project_service 格式,比如 test_db
docker-compose build [SERVICE...]
# 拉取在 Compose file 中定义的服务镜像,但不启动容器
docker-compose pull [SERVICE...]
# 推送服务镜像
docker-compose push [SERVICE...]
Compose file 示例
docker-compose.yml
version: '3.7'
services:
db:
image: postgres:14.3
container_name: postgresql
restart: on-failure
environment:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
volumes:
- /var/postgres_data:/var/lib/postgresql/data
networks:
- devops
pgadmin:
image: dpage/pgadmin4
container_name: pgadmin4
restart: on-failure
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_PASSWORD: admin-password
ports:
- 5050:80
volumes:
- /var/pgadmin_data:/var/lib/pgadmin
networks:
- devops
jenkins:
image: jenkins/jenkins:lts-jdk11
container_name: jenkins
restart: on-failure
environment:
JENKINS_OPTS: --prefix=/jenkins
JAVA_OPTS: -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=7890 -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=7890
ports:
- 8080:8080
- 50000:50000
volumes:
- /var/jenkins_home:/var/jenkins_home
networks:
- devops
jenkins-inbound-agent:
image: jenkins/inbound-agent
container_name: jenkins-inbound-agent
depends_on:
- jenkins
init: true
restart: on-failure
environment:
JENKINS_URL: "http://jenkins:8080/jenkins"
JENKINS_SECRET: "32ef99b39f55e1e3d4d717d5ae4db42384b09fb5acc524bf795f0e72f46ba9c8"
JENKINS_AGENT_NAME: "Agent"
JENKINS_AGENT_WORKDIR: "/home/jenkins/agent"
networks:
- devops
nginx:
image: nginx:1.21.6
container_name: nginx
restart: on-failure
ports:
- 8088:80
- 8443:443
volumes:
# sudo chown 101.101 /var/nginx_conf
- /var/nginx_conf:/etc/nginx/
networks:
- devops
nexus:
image: sonatype/nexus3:3.39.0
container_name: nexus3
restart: on-failure
ports:
- 8081:8081
volumes:
- nexus-data:/nexus-data
networks:
- vpc
# 创建自定义网络,如果不使用 name 属性指定网络名,所创建的网络名称是 "当前目录名_网络名"
networks:
vpc:
name: devops
有些选项需要特定版本支持,比如 init
选项只在 compose file 3.7 版本后才可用,此时需要指定 version: "3.7"
。可以查看官网的 Compatibility matrix 来了解可用的 compose file 版本以及对应的 docker 版本要求。
为 Docker Daemon 设置代理
Dockerd 代理
在执行 docker pull
时,是由守护进程 dockerd
来执行。因此,代理需要配在 dockerd
的环境中。
如果是直接启动 dockerd
,则在命令前直接加入环境变量
HTTP_PROXY=http://127.0.0.1:8080 HTTPS_PROXY=http://127.0.0.1:8080 dockerd
如果是 systemd
启动的系统,可以在 systemd
的 docker 服务中配置这环境变量。
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/proxy.conf
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:8080/"
Environment="HTTPS_PROXY=http://127.0.0.1:8080/"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"
修改后通过 systemctl
命令重新加载配置并重启 docker 使代理生效
sudo systemctl daemon-reload
sudo systemctl restart docker
参考官方文档 Control Docker with systemd
Container 代理
在容器运行阶段,如果需要代理上网,则需要配置 ~/.docker/config.json
文件。 以下配置,只在Docker 17.07及以上版本生效。
{
"proxies":
{
"default":
{
"httpProxy": "http://127.0.0.1:7890",
"httpsProxy": "http://127.0.0.1:7890",
"noProxy": "*.test.example.com,.example2.com,127.0.0.0/8"
}
}
}
这个是用户级的配置,除了 proxies
,docker login
等相关信息也会在其中。 而且还可以配置信息展示的格式、插件参数等。
此外,容器的网络代理,也可以直接在其运行时通过 -e
或 --env
注入 http_proxy
等环境变量。这两种方法分别适合不同场景。config.json
非常方便,默认在所有配置修改后启动的容器生效,适合个人开发环境。在 CI/CD 的自动构建环境、或者实际上线运行的环境中,这种方法就不太合适,用 -e
注入这种显式配置会更好,减轻对构建、部署环境的依赖。当然,在这些环境中,最好用良好的设计避免配置代理上网。
代理配置后会立即生效。
官方文档 Configure Docker to use a proxy server
Docker Build 代理
虽然 docker build
的本质,也是启动一个容器,但是环境会略有不同,用户级配置无效。在构建时,需要注入 http_proxy
等参数。
docker build . \
--build-arg "HTTP_PROXY=http://127.0.0.1:7890/" \
--build-arg "HTTPS_PROXY=http://127.0.0.1:7890/" \
--build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" \
-t your/image:tag
执行时代理立即生效
Escape Sequence
使用 escape sequence 在容器内退出容器而不停止容器。注意:容器必须以 docker run -it 选项启动该按键序列才有效
CTRL-p CTRL-q
docker run -t -i
→ can be detached withCTRL-p CTRL-q
; and reattached with docker attachdocker run -i
→ cannot be detached withCTRL-p CTRL-q
; will disrupt stdindocker run
→ cannot be detached withCTRL-p CTRL-q
; can SIGKILL client; can reattach with docker attach
如果容器是以 docker-compose 启动,使用以下 escape sequence 退出容器而不停止容器
CTRL+\