计算机 · 2021年5月23日 0

docker笔记

官方教程

网上看到的不错的教程:

  • https://segmentfault.com/a/1190000007875949

测试docker版本

docker --version
docker info

为了免得每次跑docker命令都要输sudo,执行以下命令把自己添加到docker组里:

sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker  
docker run hello-world

基础命令

  • 列出已下载镜像
  docker image ls
  • 列出正在运行的容器
  docker ps

把已经停止的容器也列出来

  docker container ls --all
  docker ps -a

列出所有的容器,但是只列出id,不显示其他多余信息

  docker ps -a -q
  • 删除镜像
  docker rmi <image-name/image-id>
  • 删除容器
  docker rm <contianer-name/container-id>

容器停止后并不会自动销毁,还需要手动去删除。

  docker start <container-id>
  docker exec -it <container-id> bash
  • 查看容器里的应用程序的日志
    在没有使用syslog这种日志函数或者其他日志工具的情况下,程序的日志基本上都是输出到stdout,stderr的,那么在以daemon模式启动容器后,如何查看容器里应用程序的stdout、stderr输出呢?
    docker把容器里应用程序的stdout,stderr保存了起来,可以通过logs命令查看:
  docker logs <container-id>

或者像tail -f一样查看:

  docker logs -f <container-id>
  docker logs --follow <container-id>

除了使用logs命令来查看日志,也可以考虑在构建docker镜像时,在CMD命令里加上stdout、stderr的重定向,直接把输出重定向到指定文件里面。

构建docker镜像

nodejs应用容器化的教程

建一个新目录,并在其中建立含有以下内容的Dockerfile文件:

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
# 后面的CMD命令会把这个路径作为working directory
WORKDIR /app

# Copy the current directory contents into the container at /app
# 这个貌似有点坑,因为如果是命令行里的cp命令的话,会把整个目录拷贝到/app里面,而对于docker来说则是把目录里的内容拷贝到/app目录下
# 也可以考虑使用ADD命令,ADD命令的源地址可以是一个url
COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
# 用字符串数组的方式描述docker默认执行的命令,比直接写要运行的命令要保险,避免docker解释命令时出现意向不到的错误
CMD ["python", "app.py"]

建立文件requirements.txt:

Flask
Redis

建立文件app.py:

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

执行构建命令:

docker build --tag=friendlyhello .

然后查看刚才生成的docker镜像:

docker image ls

运行刚才生成的docker镜像:

docker run -p 4000:80 friendlyhello

访问本机端口4000就可以看到成功访问了docker容器提供的http服务了。

以守护进程模式运行:

docker run -d -p 4000:80 friendlyhello

如果想要结束这个以守护进程模式运行的container,先找到这个container:

docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
89bb80480b65        friendlyhello       "python app.py"     9 seconds ago       Up 7 seconds        0.0.0.0:4000->80/tcp   suspicious_cartwright

然后

docker container stop 89bb80480b65

docker网络

  • [如何在容器中访问宿主机的网络?][https://stackoverflow.com/a/31328031/5357784]
    答案是使用宿主机中的docker0网口即可。
  • 同一个机器上不同容器之间通信
    如果没有用--netowrk自定义网络的话,那么用docker inspect <container>里显示的ip地址通信就可以了。

https://stackoverflow.com/questions/17157721/how-to-get-a-docker-containers-ip-address-from-the-host

在使用docker bridge模式作端口映射时,每个映射的端口会占用几MB级别的内存,因此如果设置了给一个容器映射大量端口,那么可能会导致该容器占用大量内存出错。

docker镜像的分发

将自己做好的镜像上传到dockerhub上,分享给他人

docker login
#docker tag image username/repository:tag
docker tag friendlyhello gordon/get-started:part2
#docker push username/repository:tag
docker push gordon/get-started:part2

运行dockerhub上的镜像

docker run -p 4000:80 username/repository:tag

不想将自己的镜像公开上传到dockerhub上的话,那么可以考虑自己搭建harbor进行镜像管理,或者通过docker importdocker save等命令以文件的方式传输。

使用k8s部署多个docker容器并进行管理

本来看了两眼docker service,docker swarm,感觉操作简单、明白易懂,可是后来发现在容器应用部署领域k8s才是主流,所以就不打算继续花时间了解docker swarm相关技术了。

docker自动重启

通过restart参数可以设置docker的重启策略:

  • no
    默认不重启
  • on-failure
    docker进程以非0的错误码退出时重启
  • always
    总是重启。如果是手动停止的容器,那么需要重启dockerd后才会自动重启或者手动重启。
  • unless-stopped
    alwyas类似,但是手动停止后即使重启了dockerd也不会自动重启。

例子:

docker run -d --restart unless-stopped redis

docker run与docker start的区别

如评论中所说,可理解为run = create + start。

image重命名

docker tag 0e5574283393 fedora/httpd:version1.0

container重命名

docker rename CONTAINER NEW_NAME

清理无用的containter与镜像

docker system prune [OPTIONS]

docker镜像的迁移

  1. 可以使用docker hub,就像git那样通过一个仓库来同步镜像;
  2. 把镜像导出为文件然后再进行迁移;
    使用docker import/export来迁移镜像,使用docker save/load来迁移容器;

docker磁盘空间清理

  • https://medium.com/better-programming/docker-tips-clean-up-your-local-machine-35f370a01a78

查看占用的磁盘空间

docker system df

清理磁盘空间

docker system prune

与volume有关的命令:

docker inspect [volume]
docker volume prune
docker volume ls
  • https://docs.docker.com/engine/reference/commandline/volume_prune/

关于volume的使用:

  • https://www.jianshu.com/p/ef0f24fd0674
  • https://docs.docker.com/storage/volumes/