Skip to content

docker

A container creation and management tool.

  • Ensure the consistency of production enviroment and development enviroment.
  • Ensure the consistency of different development enviroments.

Compare to Virtual OS: the latter consumes too much redundant resources.

容器化 vs 虚拟化:

  • (HyperKit是一种轻量级虚拟化方法)

  • Docker Engine

  • Docker Desktop(CLI)
  • Docker Hub

配置

国内的 Docker Hub 镜像加速器,由国内教育机构与各大云服务商提供的镜像加速服务 | Dockerized 实践 https://github.com/y0ngb1n/dockerized

Images & Containers

Images: Templates/Blueprints for containers

is automatically exposed to us by container..we're not expoing any port here

docker run -it node

  • Dockerfile
FROM node # base image
WORKDIR /app
COPY . /app # orginal folder, dest folder; or "./" relative to WORKDIR
RUN npm install
EXPOSE 3000
CMD ["node", "server.js"] # CMD executes after the container is created based on this image, always the last line
  • Layer based architecture: Dockerfile 里的every instruction 都可以视为一个 read-only layer, 最后运行的时候,会再加一层 Container Layer(read-write) 所以会有多个container, 但只有一个image内的代码,不会复制多次的。

另外,制作image 的 layer 可以缓存,所以记住容易发生更改的指令要放后面,一个小小的优化点。

  • docker build . (. 指相对于 Dockerfile 的定位) -t vikki77/name:tag (注意,好习惯一定要打标)
  • docker tag kub-first-app vikki77/kub-first-app // add tag afterwards
  • docker push vikki77/kub-first-app
  • docker run -p localPort:targetPort docker_id
  • docker stop docker_name

Docker Run

  • docker run -p 3000:3000 -v "$(pwd)/ss:/files/ss" -d imageName // Detach mode
  • docker attach container-id
  • docker start -a container-id
  • -i(interative) -t(pseudo-tty)
  • --rm // 退出container 后自动清理文件系统
  • docker exec -it ... ... <container id> /bin/bash
  • docker exec -it <container id> /bin/sh
  • docker inspect <container id>

Docker ps

  • --filter "name=registry" --filter "ancestor=registry" // from image 是什么

Docker rm

  • docker rm container
  • docker rmi image
  • docker image prune // unused/tangling悬空 images

Pretty error-prone.

Its not sth. we will use very often in ..., but still a sth. you should be aware of.

docker cp: copy some logs to local host machine. docker cp foo.txt container_id:/foo.txt

Docker logs - docker logs -f --until=2s --tail=20 nginx (-f 代表 --follow) - 加上 grep: docker logs -f --until=2s --tail=20 nginx 2>&1 | grep "127."

data

  • Managed by Docker

  • in dockerfile:\anoymous Volumes, attached to one container, gone when one contained shut down -v thePathToBeMaintained

  • Named Volumnes: data shared by containers, wont be deleted, -v name:thePathToBeMaintained

  • Managed by host

  • bind mounts: editing & persistent data, -v absolutePath:thePathToBeMaintained

Eh..有一个就是 include + exclude 的情况 e.g -v "$(pwd):/app" -v /app/node_modules,这样后者里的node_modules 就不会被覆盖(不过直接在 .dockerignore 里写就好了呀

p.s. 我用 minikube 做 docker-daemon, bind mount 的 volumn 未绑定上,是个 bug, 参考 https://gist.github.com/gitjonez/eac3cf6d3a963e5077875dcf0e7e73ee

others

  • ENV vairable: ENV PORT 80 \n EXPOSE $PORT ;使用:-e PORT=3000 或 --env-file env
  • build-time arguments: ARG DEFAULT_PORT=80;使用 docker build xx --build-arg DEFAULT_PORT=8000

networks

  • container vs host machine: localhost:27017 => host.docker.internal:27017

Docker 实际上工作在另一网段?通过 docker inspect xxcontainer 可以看到 ip

  • container vs container: docker network create netname; docker run ... --network netname; and use containername:port

注意前端请求后端只能用 后端服务暴露出端口 的模式哦。

utility containers

Running Commands in Containers

  • docker run -it node
  • docker run -it -d node; docker exec containerName npm init;
  • docker run -it node npm init

ENTRYPOINT ["npm"] will append after this entrypoint

docker-compose

  • docker-compose up [-d] (--build) // detach, force build
  • Docker-compose down [-v] // 是否要 remove volumes
version: "3.8"
services:
  mongodb:
    image: 'mongo'
    volumes: 
      - data:/data/db
    # environment: 
    #   MONGO_INITDB_ROOT_USERNAME: max
    #   MONGO_INITDB_ROOT_PASSWORD: secret
      # - MONGO_INITDB_ROOT_USERNAME=max
    env_file: 
      - ./env/mongo.env
    container_name: mongodb
  backend:
    build: ./backend
    # build:
    #   context: ./backend
    #   dockerfile: Dockerfile
    #   args:
    #     some-arg: 1
    ports:
      - '80:80'
    volumes: 
      - logs:/app/logs
      - ./backend:/app
      - /app/node_modules
    env_file: 
      - ./env/backend.env
    depends_on:
      - mongodb
  frontend:
    build: ./frontend
    ports: 
      - '3000:3000'
    volumes: 
      - ./frontend/src:/app/src
    stdin_open: true
    tty: true
    depends_on: 
      - backend

volumes: 
  data:
  logs:

安装相关

On Mac, brew install docker: cannot-connect-to-the-docker-daemon-on-macos

macOS the docker binary is only a client and you cannot use it to run the docker daemon, because Docker daemon uses Linux-specific kernel features, therefore you can’t run Docker natively in OS X. So you have to install docker-machine in order to create VM and attach to it.

Difference between Docker Desktop and Docker

Docker Desktop = a virtual machine with a Docker CE (Docker Community Edition) daemon + gui + run a single-node kubernetes "cluster" easily

Docker Engine is an open source containerization technology for building and containerizing your applications. Docker Engine acts as a client-server application with:

  • A server with a long-running daemon process dockerd 23.
  • APIs which specify interfaces that programs can use to talk to and instruct the Docker daemon.
  • A command line interface (CLI) client docker 15.

使用 brew 安装时要注意,brew install docker只安装了client,但是brew install --cask docker; open /Applications/Docker.app会安装整个 desktop.

原理相关

docker 如何判断容器内服务正常运行中?之前就看容器内主进程是否已退出,若出现主进程卡住的情况,还可指定 HEALTHCHECK 指令获取返回值

实践

registry

Docker Registry | Docker Documentation 已 move 到这里 基于Docker搭建私有镜像仓库 - 腾讯云开发者社区-腾讯云 用户账密、使用 ip 时的 insecure-registries 需要注意。

所有api: - 镜像列表: https://hub.lmhdev.com/v2/_catalog - tagList: - curl 172.24.137.212:5000/v2/ztlydev/byteox-message/tags/list - curl http://10.0.1.48:5000/v2/ztlydev/byteox-house/tags/list

golang 实践

  • 多阶段
  • 镜像基底注意选择 alpine (scartch太原始了),但是使用 alphine, 也有部分需要额外设置的地方,比如时区

构建 Golang 应用最小 Docker 镜像 - 掘金

如何构建 Go 应用的 Docker 镜像 - 掘金

不要轻易使用 Alpine 镜像来构建 Docker 镜像,有坑! - 腾讯云开发者社区-腾讯云

docker container stop registry && docker container rm -v registry

docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  registry:2

logs: /logs/lmh_api_test

文件: /opt/project/lmh_api_test

要往外获取的网络:

  • port 8848 utils.InitNanos(conf.ConfigServer.IPAddr, uint64(conf.ConfigServer.Port)
  • Mysql, redis 127.0.0.1 要改成本机 ip

要往外暴露的网络:

  • 8080 -> 开启的 port 都统一成 8080

日志初始化服务需要重新配置

docker build -t lmh_api_server .

docker run -p 8090:8080 -v "/logs/lmh_api_test:/logs" -v "/opt/project/lmh_api_test/cmd:/cmd" --add-host=host.docker.internal:host-gateway lmh_api_server:latest

docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  -v  /auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  registry:2

docker login:

docker login --username=testuser --password=****** hub.lmhdev.com

push image:

docker tag 518a41981a6a hub.lmhdev.com/myPrivateImage && docker push hub.lmhdev.com/myPrivateImage

执行 test:

docker login --username=testuser --password=testpassword hub.lmhdev.com
docker pull hub.lmhdev.com/lmh_api_test:latest
docker stop lmh_api_test
docker rm lmh_api_test
docker run -d \
    -p 8090:8080 \
    -v "/logs/lmh_api_test:/logs" \
    -v "/opt/project/lmh_api_test/cmd:/cmd" \
    --add-host=host.docker.internal:host-gateway \
    --name lmh_api_test \
    hub.lmhdev.com/lmh_api_test:latest

清理

移除无用(悬空)的 docker 镜像

  • docker rmi $(docker images --filter "dangling=true" -q --no-trunc)
  • docker image prune

移除 registry image From file system

出现情况:在 /lib/docker/volumes/registry的volumes_id/data/blob 下占用 22G,但实际存有的 image list 只有 1G 左右。冗余的历史镜像,包括没有 tag 的镜像,都需要手动清除。

tag is composed of several layers. The list of the layers for that particular digest is called a manifest. There is a corresponding blob for each layer. There can also be layers which are not used by any of the tags — those are called abandoned or unused layers. Those corresponding blobs are also unused. We can delete them to gain some space on the disk.

docker image

可在 registry 容器内 run the garbage collector: $ docker exec registry bin/registry garbage-collect --delete-untagged /etc/docker/registry/config.yml Ref: How to maintain a Private Docker Registry? | by Janeth Fernando | Medium