Docker - zhongjiajie/zhongjiajie.github.com GitHub Wiki

docker

相关书籍

docker相关基础

配置

基础知识

  • docker-compose中的depends_on会依据依赖顺序启动服务,被depends_on的容器会先启动,但是主动depends_on的容器不会等到被depends_on,例如下面的例子:db,redis容器启动顺序要优先于web容器;当启动 web容器时会自动创建redis和db容器.不过需要注意的是,depends_on不会等到db和redis容器ready再启动,web容器仅仅等到redis和db容器启动就开始启动.具体可参考官网启动顺序了解
version: '2'
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

dockerignore

和gitignore一样,用于忽略掉部分不需要的文件,用于加快传输文件到 docker 上下文。写法有很多种:

  • 将部分build不需要的文件写入dockerignore文件:这个是按需排除不需要的文件

  • 仅将build需要的文件写入dockerignore文件:反向思考,参考例子是apache-airflow的dockerignore

    # Ignore everything
    **
    
    # Allow only these directories
    !airflow
    !common
    !dags
    !dev
    !docs
    !licenses
    !scripts
    !tests
    

基础命令

run

ps

  • docker ps: 查看正在运行的容器
  • docker ps -a: 查看全部容器包括已经退出的容器
  • docker ps -s: 查看正在运行的容器信息(包括大小)

cp

Copy files/folders between a container and the local filesystem.

  • docker cp src container:dest: 从宿主机复制文件/文件夹到docker容器
  • docker cp container:src dest: 从docker容器复制文件/文件夹到宿主机

network

  • 查看network下的Containers的具体内容docker network inspect --format='{{range .Containers}}{{println .Name}}{{end}}'
  • 清除一个network中的所有active endpoints: docker network inspect --format='{{range .Containers}}{{println .Name}}{{end}}' <network_name> | xargs -I % echo 'docker network disconnect <network_name> %' | sh

inspect

用于查看对象详细信息

  • --format: 详见Format command and log output
    • join: concatenates a list of strings to create a single string
    • json: encodes an element as a json string
    • lower: transforms a string into its lowercase representation
    • split: slices a string into a list of strings separated by a separator
    • title: capitalizes the first character of a string
    • upper: transforms a string into its uppercase representation
    • println: prints each value on a new line

system

  • docker system prune: clean up all images, containers, networks, volumes not used,offical-system
  • docker system prune -a --volumes: clear all including volumes, 只要是没有container使用的volumes都会被清除,这可能会带来关键数据丢失的问题,使用前请注意

tag

基本命令

/img/docker-basic-command.png

  • 进入 docker 容器 docker exec -it container_name bash
  • docker 删除虚悬镜像 docker rmi $(docker images -f dangling=true)
  • 删除所有停止/退出镜像 docker rm $(docker ps -aq -f status=exited) -f 是过滤参数
  • docker-compose 运行指定 yml 文件 docker-compose -f docker-compose-file.yml up -d
  • 用 docker-compose 部署的时候如果要先build一些东西的话,可以直接在 service 下面放一个 build 任务,部署的时候用 docker-compose up --build 如果没有 --build 的话就会引用已经存在的镜像,没有更新到
  • docker格式化ps输出 docker ps -format 'table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.CreatedAt}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}' 这是docker ps的原生输出,format后面的table是格式化输出成表格
  • docker-compose重启单个workerHow to restart a single container with docker-compose: docker-compose restart worker可以设置时间等待杀死容器docker-compose restart -t 30 worker
  • docker-compose停止其中一个容器: docker-compose stop service-name
  • docker-compose通过scale来创建多个容器: docker-compose version 2 docker-compose scale service_a=3; docker-compose scale service_b=3会生成3个service_a和3个service_b, 如果docker-compose version 3的话要达到同样的效果要docker-compose up -d --scale service_a=3 --scale service_b=3 --no-recreate而不能单独的运行docker-compose up -d --scale <service_name>=3这个会只生成3个service_name容器
  • 将本机容器制作导出: docker save IMAGE | gzip > LOCAL_IMAGE.gz,将导出的镜像导入: docker load -i LOCAL_IMAGE.gz

网络相关

Dockerfile

multi-stage build

Dockerfile 的 multi-stage build 属性允许你创建更小的镜像,更好的使用cache,为每个特定的镜像编写更加小的entrypoint,了解更多查看这里

# 在dockerfile文件中指定镜像的版本 可以在构建镜像时使用 `--build-arg UBUNTU_VERSION=value` 修改镜像的版本
# 如果么有传对应的值 则会以默认的版本(18.6)进行构建
ARG UBUNTU_VERSION=18.6

# 可以对当前的 stage 进行别名方便后面的 stage 调用
FROM ubuntu:${UBUNTU_VERSION} AS base
RUN apt-get update && apt-get install git

# 可以从之前的 stage 中来
FROM base AS src1
RUN git clone …

FROM alpine
# --from 可以直接从已有的镜像中拿对应的值
# 也可以使用之前已经完成的stage,如 `--from=base`
COPY --from=linuxkit/ca-certificates / /

# 可以使用更加有意义的别名 如对 release 镜像衍生出 dev-env test 镜像分别用于开发和测试
FROM scratch AS release
FROM golang:alpine AS dev-env
COPY --from=release / /
ENTRYPOINT ["ash"]
FROM golang:alpine AS test
COPY --from=release / /
RUN go test …

先编译然后复制编译后的值

FROM nodejs as builder
WORKDIR /usr/src/app
COPY . .
RUN npm build

FROM nginx
COPY --from=builder /usr/src/app/build/ /nginx_home

docker-compose

docker-compose汇总

  • docker-compose up -d --no-build: docker-compose启动但是不重新build镜像

ulimits

指定容器的 ulimits 限制值。例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制) 和 40000(系统硬限制,只能 root 用户提高)

  ulimits:
    nproc: 65535
    nofile:
      soft: 20000
      hard: 40000

example

docker FAQ

  • Cannot install packages inside docker Ubuntu image: should apt-get -qq update first, because no package cache in the image
  • docker-mysql用数据卷自定义配置之后connect mysql会变慢,可以在自定义配置文件section mysqld增加skip-name-resolve选项
  • docker-mysql自定义文件编码section mysql&client default-character-set=utf8 并且 section mysqld character-set-server=utf8
  • docker Hub Automated Build with specify tag
  • docker build如果上一次运行成功,下次再运行会直接使用cache,docker build --no-cache可以指定不使用cache,How to force docker for clean build of an image
  • docker默认的registry地址https://index.docker.io/v1/,可以通过docker info | grep -i registry得到docker中所有的信息.如果国内镜像仓库中部分镜像没有更新(例如自己编译的镜像没有及时更新),docker pull registry.hub.docker.com/library/busybox

不要以root用户运行容器

docker的其中一个最佳实践就是不要已root用户运行容器,因为容器中的root和宿主机中的root(uid 0)是同一个,这意味着在容器用户可以对宿主机文件目录进行读写,这样会导致很多可能的问题.相见这里

docker模拟网址

play-with-docker: t’s an online playground where you can test all the latest Docker features without having to install anything locally

docker中中文乱码

进入对应image生成的容器中,输入locale查看支持什么编码, C.UTF-8以及zh_CN.UTF-8都可以,但是大部分docker镜像都只有C.UTF-8,之后在dockerfile中增加一行ENV LANG C.UTF-8即可,如果还不行就增加

ENV LANGUAGE C.UTF-8
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
ENV LC_CTYPE C.UTF-8
ENV LC_MESSAGES C.UTF-8

docker开放远程API调用

  • 开启docker远程调用API端口
    • MAC: 根据docker/for-mac:ISSUE-770,默认不开启远程调用端口,可以fork一个容器开启端口docker run -d -v /var/run/docker.sock:/var/run/docker.sock -p 127.0.0.1:2375:2375 bobrik/socat TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock,然后export DOCKER_HOST=unix:///var/run/docker.sock
    • Linux:
    • Windows: 点击docker图标,在设置->通用选项勾选Expose daemon on tcp://localhost:2375 without TLS
  • 在docker-deamon运行的机器中,检查端口是否开放netstat -anp | grep 2375或者lsof -i:2375
  • 在docker-deamon运行的机器中,检查能否通过tcp访问docker-deamon,docker -H tcp://localhost:2375 images
  • 在需要调用remote-api的机器检查2375端口是否开启,telnet <IP>:2375,如果上面都能成功倒是这步不成功,就是服务器防火墙没有开放2375端口,开放端口即可

pycharm中使用docker中的解释器

参照Configure a remote interpreter using Docker,需要根据docker开放远程API调用先启动远程调用端口,然后新增配置解释器配置.如果是离线的话需要busybox:latest以及pycharm_helper:PY-<对应的版本号>

docker build 时 apt-get 的速度慢的解决办法

和本机apt-get慢是同一解决办法,使用国内的源,使用的方式参考tenxcloud/docker-debian,将国内源写入sources.list文件,使用时在Dockerfile中使用COPY sources.list /path/to/docker_sources.list替换原来的源,最后在RUN中运行apt clean \ && apt update

docker build 中需要使用代理下载

docker在本地build的时候可能需要下载需要翻墙的二进制包,可以参考SO,在docker的configure中配置proxy属性,然后重启docker就能使用了。如果是mac客户端的话,可以在Prefrences -> Resources -> PROXIES开启手动代理配置,然后重启docker

docker build时COPY ADD提示文件不存在

相关的[SO][]可能原因如下:

  • 文件路径写错:文件路径可能比较复杂,导致本地路径写错。此时修改成正确路径即可
  • 运行docker build的路径错了:本应该在指定路径运行docker build的,但却在别的路径下运行了。此时切换到正确的路径即可
  • dockerignore文件错误:要COPY/ADD的文件在dockerignore文件中,或者dockerignore仅允许指定文件发送到docker上下文中。此时检查dockerignore的配置然后修改即可

docker-compose运行时发现COMPOSE_HTTP_TIMEOUT

更加可配置地方案是,编辑.env文件,加入COMPOSE_HTTP_TIMEOUT=200项目SO

MAC配置2375端口可以登录

docker的mac默认不启动2375端口,参考,方便的方式是直接写一个快捷方式到zshrc

alias docker-api-start='docker run -d -v /var/run/docker.sock:/var/run/docker.sock -p 127.0.0.1:2375:1234 --name docker-api bobrik/socat TCP-LISTEN:1234,fork UNIX-CONNECT:/var/run/docker.sock'
alias docker-api-stop='docker rm -f docker-api'

Tips

  • 当遇到部分 Dockerfile 没有办法没有正确写出来的时候,可以去 github 搜索一下 base images + pkg_to_install
  • 当遇到本地 docker build 过慢时,可以将 Dockerfile 放到 github 上,然后在 docker hub 上设置对应 automated-build 当提交到 github master上后就会自动 build
  • 如果从国内镜像中pull镜像失败,可以直接去dockerhub官网拉取docker pull registry.hub.docker.com/zhongjiajie/docker-airflow
  • centos7安装docker之后可能出现不能打开端口的情况,根据configure Centos7 firewallD to allow docker containers free access to the host's network ports
    • firewall-cmd --permanent --zone=trusted --change-interface=docker0
    • firewall-cmd --permanent --zone=trusted --add-port=4243/tcp
    • firewall-cmd --reload
    • systemctl restart docker.service

script

一些docker相关的shell脚本

  • 删除dangling镜像和停止的容器

    echo "remove dangling images"
    if [[ ! -z $(docker images -f dangling=true -aq) ]]; then
      docker rmi $(docker images -f dangling=true -aq)
    fi
    echo "remove extied container"
    if [[ ! -z $(docker ps -aq -f status=exited) ]]; then
      docker rm -f $(docker ps -aq -f status=exited)
    fi
  • 备份非dangling的容器

    echo "backup not dangling images"

Ref


⚠️ **GitHub.com Fallback** ⚠️