Docker 简单笔记

Posted by YuCong on December 21, 2021

Docker 简单笔记


Created 2021.12.24 by William Yu; Last modified: 2022.07.12-V1.2.6

Contact: windmillyucong@163.com

Copyleft! 2021 William Yu. Some rights reserved.


Docker 简单笔记

Reference

  • https://docs.docker.com/
  • https://docker.easydoc.net/doc/
  • https://docs.docker.com/engine/install/ubuntu/
  • https://yeasy.gitbook.io/docker_practice/
  • https://yeasy.gitbook.io/docker_practice/

1. Install

  • https://docs.docker.com/engine/install/ubuntu/
    • https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository
  • https://docs.docker.com/compose/install/

1.1 Install docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sudo apt-get update

sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
    
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  
 sudo apt-get update
 sudo apt-get install docker-ce docker-ce-cli containerd.io

确认是否安装成功

1
docker run --rm hello-world

看到如下输出即可

1
Hello from Docker!

备注:可能出现的问题

问题1.

1
W: GPG error: https://apt.dockerproject.org ubuntu-trusty InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY F76221572C52609D
1
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

如果是使用zsh之类的shell可能会出现此问题。 原因:输入的y 不能被正常捕获,然后key不能被正常加载。

检查key文件,检查权限与文件大小

1
2
$ ls -lh /usr/share/keyrings/docker-archive-keyring.gpg
-rw-r--r-- 1 root root 0 1月   5 12:48 /usr/share/keyrings/docker-archive-keyring.gpg

2.7k

1
2
$ ls -lh /usr/share/keyrings/docker-archive-keyring.gpg
-rw-r--r-- 1 root root 2.7K 1月   5 13:02 /usr/share/keyrings/docker-archive-keyring.gpg

问题2.

https://blog.csdn.net/CaoMei_HuaCha/article/details/87544109

1.2 Install Docker compose

1
2
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

确认是否安装成功

1
docker-compose --version

1.3 权限

1
sudo usermod -aG docker trifo

2. 基本概念

2.1 镜像(Image

相当于操作系统安装包

2.2 容器(Container

镜像是静态的,容器是镜像运行的实体。相当于安装在计算机上的操作系统

2.3 仓库(Repository

  • 一个 Docker Registry 中可以包含多个 仓库Repository
  • 每个仓库可以包含多个 标签Tag);每个标签对应一个镜像。

3. 启用 docker

启动docker

1
2
$ sudo systemctl enable docker
$ sudo systemctl start docker

4. 镜像

镜像的相关操作:

获取远程镜像
1
$ sudo docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
列出所有镜像

列出所有本地镜像

1
$ sudo docker image ls

或者从Dockerfile build 镜像。

由镜像创建容器
1
docker run -ti -d --name <容器名称> <镜像名称:版本>
镜像推送

用户可以将自己的镜像推送到 Docker Hub,Docker Hub 是一个由 Docker 公司运行和管理的基于云的存储库。它是一个在线存储库,Docker 镜像可以由其他用户发布和使用。有两种库:公共存储库和私有存储库。如果你是一家公司,你可以在你自己的组织内拥有一个私有存储库,而公共镜像可以被任何人使用。

1
docker push <REPOSITORY>:<TAG> # 注意:不满足格式要求

推送到hub的镜像遵守需要命名规则 <user_name>/<REPOSITORY>:<TAG>

修改镜像的名称
1
docker tag <REPOSITORY>:<TAG> <user_name>/<REPOSITORY>:<TAG>

然后push

1
docker push <user_name>/<REPOSITORY>:<TAG>
镜像导出为文件
1
docker save -o <file_name>.tar <REPOSITORY>:<TAG>
从文件导入镜像
1
docker load -i <file_name>.tar

5. Dockerfile

Dockerfile用于编译镜像。

Dockerfile编写
  • 注意dockerfile文件夹下面最好不要有其他东西
1
vim Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
FROM ubuntu:latest

LABEL maintainer="zhonger zhonger@live.cn"

# Create a no-passowrd sudo user
RUN apt update \
    && apt install -y sudo \
    && useradd -m ubuntu -s /bin/bash && adduser ubuntu sudo \
    && echo "ubuntu ALL=(ALL) NOPASSWD : ALL" | tee /etc/sudoers.d/nopasswd4sudo

# Adjust Timezone
ENV DEBIAN_FRONTEND=noninteractive
RUN apt install -y tzdata \
    && ln -fs /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

USER ubuntu
WORKDIR /home/ubuntu

# Install zsh
RUN sudo apt install -y git zsh \
    && git clone https://github.com/ohmyzsh/ohmyzsh.git ~/.oh-my-zsh \
    && cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc \
    && sed -i "s/robbyrussell/bira/" ~/.zshrc \
    && sudo usermod -s /bin/zsh ubuntu


# Clean apt-cache
RUN sudo apt autoremove -y \
    && sudo apt clean -y \
    && sudo rm -rf /var/lib/apt/lists/*

ENTRYPOINT ["/bin/zsh"]

用 Dockerfile build 镜像

编译生成 Docker 镜像

  • https://docs.docker.com/engine/reference/commandline/build/
1
docker build . -t zhonger/ubuntu:latest
  • . 指的是当前文件
  • -t 指定镜像的名字与版本号
    • :前面是镜像名称
    • :后面是版本号

查看结果

1
sudo docker image ls
由镜像创建docker 容器
1
sudo docker run -ti -d --name dev zhonger/ubuntu:latest
容器启动
1
docker start dev
容器执行命令
1
sudo docker exec -it dev /bin/zsh

5. 容器

容器的相关使用操作

  • https://yeasy.gitbook.io/docker_practice/container/run
创建容器

并执行终端

1
docker run -t -i ubuntu:18.04 /bin/bash
  • -t 参数 让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
  • -i 参数 则让容器的标准输入保持打开
run 命令
  • https://docs.docker.com/engine/reference/run/

创建一个新的容器并运行一个命令

1
docker run <各项参数> <镜像> <命令>

参数:

  • -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
  • -d: 后台运行容器,并返回容器ID;
  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  • –name: 为容器指定一个名称;如省略则会 Docker 会自动分配一个名称
  • –dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
  • –dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
  • -h “mars”: 指定容器的hostname;
  • -e username=”ritchie”: 设置环境变量;
  • –env-file=[]: 从指定文件读入环境变量;
  • –cpuset=”0-2” or –cpuset=”0,1,2”: 绑定容器到指定CPU运行;
  • -m :设置容器使用内存最大值;
  • –net=”bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
  • –link=[]: 添加链接到另一个容器;
  • –expose=[]: 开放一个端口或一组端口;
  • –volume , -v: 绑定一个卷
启动容器
1
docker start dev
exec 命令

在容器中直接执行命令

1
$ docker exec -it <CONTAINER ID>或者<NAMES> <执行的命令>

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建容器
$ docker run -dit ubuntu
69d137adef7a8a689cbcb059e94da5489d3cddd240ff675c640c8d96e84fe1f6

# 查看容器
$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
69d137adef7a        ubuntu:latest       "/bin/bash"         18 seconds ago      Up 17 seconds                           zealous_swirles

# exec -i 参数
$ docker exec -i 69d1 bash
ls
bin
boot
dev
...

# exec -it 参数
$ docker exec -it 69d1 /bin/bash
root@69d137adef7a:/#
  • -i 参数
  • -t 参数:分配伪终端
进入容器终端
1
docker exec -it <CONTAINER ID>或者<NAMES> /bin/bash
查看运行中的容器
1
2
3
docker container ls
或者
docker ps
查看所有容器(包含终止状态的容器)
1
2
3
docker container ls -a
或者
docker ps -a
终止运行中的容器
1
docker container stop <CONTAINER_ID>
启动容器

处于终止状态的容器,可以通过命令来重新启动。

1
docker container start <CONTAINER_ID>
终止并重启容器

该命令会将一个运行态的容器终止,然后再重新启动它。

1
docker container restart <CONTAINER_ID>
移除容器
1
docker rm <CONTAINER_ID>
容器向本机传送文件
1
docker cp container_name_or_id:容器目录 本地目录
本地向容器传送文件
1
docker cp 本地目录 container_name_or_id:容器目录
容器打包导出为镜像

打包前也可以将写好的代码放在容器里面,有利于快速部署

1
docker commit container_name_or_id image_name:image_tag

6. 挂载x display 到宿主机

在docker 中使用 x display,将x display挂载到docker容器的宿主机上

1. 宿主机设置
1
2
3
# 宿主机执行
sudo apt-get install x11-xserver-utils
xhost +
2. 创建容器时添加参数

然后创建docker容器时,添加选项:

1
2
3
4
sudo docker run -it --name monitor \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  -e DISPLAY=unix$DISPLAY \
   zhonger/ubuntu:latest
3. 如果容器已经存在,可以修改参数

我们在已经启动的容器里做了一些事情,这时有了显示图像的需要,但从头新启动一个容器有点麻烦。

  1. 使用 ifconfig 查看主机和docker的IP地址

    例如:主机的IP为 xxx ;docker 的IP为YYY

  2. docker 中

1
export DISPLAY= XXX       #把环境变量映射到主机IP
  1. 主机中
1
2
sudo gedit /etc/lightdm/lightdm.conf      
#增加一行    xserver-allow-tcp=true
1
2
sudo systemctl restart lightdm
xhost  +                #注意加号前应有空格

这样配置就完成了,这是第一次配置的操作。

以后每次重新开机时,还是要在主机里运行一下 xhost +,在docker里运行一下export DISPLAY= XXX 。 其实还是挺麻烦的。

最关键的是,这种方式用的是IP地址,在系统没联网时,网卡就没有分配的IP地址了,这种方法就行不通了。

4. 怎样测试能否显示图像界面
  • 一个显示时钟的小程序xclock
  • 不过我在Ubuntu16.04的环境里搜不到这个了,能安装的叫xarclock,功能一样 。

在docker中运行

1
2
sudo apt-get install xarclock       #安装这个小程序
xarclock                            #运行,如果配置成功,会显示出一个小钟表动画

7. 目录挂载

本地目录到docker容器中

  • https://yeasy.gitbook.io/docker_practice/data_management/bind-mounts
  • https://docker.easydoc.net/doc/81170005/cCewZWoN/kze7f0ZR

三种挂载方式

  • build mount 直接将宿主机的目录映射到容器中
  • tmpfs mount 适合存储临时文件,存宿主机内存中。不可多容器共享。
  • volume 由容器创建和管理,创建在宿主机,所以删除容器不会丢失,官方推荐,更高效,Linux 文件系统,适合存储数据库数据。可挂到多个容器上

1. volume

-v
1
docker run -v <本地目的>:<容器目录> <镜像名称,如ubuntu:18.04>
  • -v 代表挂载目录
    • 本地目的和容器目录使用:分隔
    • 均是绝对路径
    • 当容器目录不存在时会自动创建
    • 如需挂载多个目录,可以使用多个-v来挂载多个目录

2. mount

–mount
1
2
3
4
docker run -it --name <容器名称> \
# -v /src/webapp:/usr/share/nginx/html \
    --mount type=bind,source=/src/webapp,target=/usr/share/nginx/html \
    <镜像名称,如ubuntu:18.04>
  • –mount 参数:
    • 以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹;
    • 而使用 --mount 参数时如果本地目录不存在,Docker 会报错。
    • 所以 mount参数更安全。
    • source 本地目录
    • target 容器目录
权限
  • 挂载主机目录的默认权限是 读写
  • 用户也可以通过增加 readonly 指定为 只读 。容器内无法更改该文件夹
1
2
3
4
5
docker run -d -P \
    --name web \
    # -v /src/webapp:/usr/share/nginx/html:ro \
    --mount type=bind,source=/src/webapp,target=/usr/share/nginx/html,readonly \
    nginx:alpine

8. Docker ssh

Dockerfile 中使用私钥
  • http://xfyuan.github.io/2020/10/build-docker-with-private-ssh-key/

但是上面的方法只是在Dockerfile中使用密钥,镜像中不在具有使用权限。

Docker 容器中添加密钥

将key复制到docker容器

1
sudo docker cp ~/.ssh/id_rsa <容器名称>:/home/trifo/.ssh/

进入 docker 容器里面

1
2
# 检查是否已经复制进
ls ~/.ssh

然后添加密钥

1
ssh-add ~/.ssh/id_rsa
1
2
# 报错
Could not open a connection to your authentication agent.

添加私钥出错,执行如下命令即可

1
2
3
$ eval `ssh-agent -s`
Agent pid 322
# 然后再 ssh-add
1
2
3
4
# ssh 使用时如果报错 
╭─trifo@e1edb7ac7304 ~/.ssh 
╰─ $ ssh 192.168.0.103                                         
Unable to negotiate with 192.168.0.103 port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1

可以使用以下参数解决

1
$ ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 192.168.0.103

或者方案二

1
2
3
4
vim ~/.ssh/config
# 然后填入
Host 192.168.*.*
    KexAlgorithms +diffie-hellman-group1-sha1
1
2
3
4
5
6
7
# 如果报错

Offending ECDSA key in /home/c/.ssh/known_hosts:55                                 
  remove with:                                                                         
  ssh-keygen -f "/home/c/.ssh/known_hosts" -R "192.168.2.196"
ECDSA host key for 192.168.2.196 has changed and you have requested strict checking.
Host key verification failed.

可以使用的解决方案

1
ssh-keygen -R 192.168.2.196

9. Docker 可视化 tool

暂略

备注:docker wechat

  • https://github.com/top-bettercode/docker-wechat 不能调整字体大小
  • https://github.com/Alice-space/docker-wechat 修复字体大小的问题
1
sudo docker pull alicespace/wechat
1
2
3
4
git clone https://github.com/Alice-space/docker-wechat.git
cd docker-wechat
chmod +x ./local_launch.sh
./local_launch.sh