230716_再学docker

Haoliang Tang Lv2

原理介绍

为什么需要docker?比如app在开发环境下能正常运行,但到了其他人的机器上因为各种环境问题导致跑不起来。

一个image就是要运行的app和运行它所必要的dependency,打包在一起变成一个package。类似.iso image

container是image的实际执行,就是一个进程(image是程序,container是进程)

ちなみに、docker也只是容器技术的一种实现,其他还有比如containerd

Architecture

Docker是client-server架构的

server也就是Docker Engine (build & run contianer)

为什么docker比虚拟机轻量,快?

docker engine启动的container其实共用本机操作系统的kernel。(默认本机是Linux,绝大部分的镜像应用都是基于linux的。而如果本机是win/mac的话,其实需要起一个linux的虚拟机。这也许也是mac/win安装docker需要docker-desktop,而linux并不需要docker-desktop的原因)

1
2
3
4
sudo docker run -t -d --name archtry archlinux
sudo docker exec -it archtry bash
uname -a
cat /proc/version

查看到的内核信息和本机一样

而虚拟机需要各自单独的内核,同时还需要一个hypervisor

==正是容器和虚拟机的本质区别在于,容器共用了本机OS的kernel,所以容器轻量快捷。但同时也是由于容器使用本机的内核,你是没办法在一台linux机器上运行windows server容器的。只能在windows机器上运行win的容器。win/mac通常跑的docker应用,实际是建了个linux虚拟机,然后在上面运行的。==

you need to learn Docker RIGHT NOW!! 解释得很好

Install Docker

安装的话,不同linux发行版的具体操作都不太一样。看https://wiki.archlinux.org/title/Docker的参考价值可能比看官网更大

1
sudo pacman -S docker

实际就是装了Docker Engine

1
2
docker -v
docker version //docker server没运行的话,就只显示client的信息

启动Docker Engine

1
systemctl start docker

其实标准的应该是systemctl start docker.service,还有docker.socket(按tab键)

systemctl start了,docker version或者docker info报permission denied的错


用户没被加入到docker group的话,各种docker操作都是需要sudo的。sudo docker version就显示出Server的信息了

https://stackoverflow.com/questions/46202475/permission-denied-while-trying-to-connect-to-the-docker-daemon-socket

https://wiki.archlinux.org/title/Users_and_groups#Group_management

将用户加入到docker group

Add the user to the docker group to avoid permission issues:

1
sudo usermod -aG docker <your_username>
1
systemctl restart docker	//再不行就重启电脑

こうやって実行すれば、be able to run the docker CLI command as a non-root user

之后的docker命令行操作就不需要sudo

但最好不要为了少打个sudo,就这样操作。因为这个用户可能就有了系统权限。从安全的角度考虑别这样做。

Docker Compose

1
sudo pacman -S docker-compose
1
docker-compose -v

Docker Desktop

https://docs.docker.com/get-docker/ 这里Docker Desktop就是Docker Engine加上a bunch of其他的tools

An experimental package for Arch is provided directly by Docker; see the manual for more information. Unfortunately it contains files which conflict with the docker-compose package so you will first need to remove docker-compose if installed. Alternatively, you can install docker-desktop AUR package that does not conflict with existing packages.
(From https://wiki.archlinux.org/title/Docker )

所以,装aur的docker-desktop

1
yay -S docker-desktop

操作

docker image并不是一个存储在当前工作目录的单文件。how Docker stores image is very complex,我们也先不管它

查看本机的所有image

1
docker images

or ls(short for list)

1
docker image ls

只pull下来镜像,但不运行

1
docker pull archlinux

Create and run a new container from an image (没有的话会自动pull)

1
docker run nginx

可以随便在什么目录下运行,因为必要的环境都在image里

docker run可以理解为docker create附带第一次执行

https://docs.docker.com/engine/reference/commandline/create/ 搞明白create, run, start的联系

交互式地运行,直接run会瞬间退出 (但也由此可见容器的启动速度比虚拟机快多了)

1
sudo docker run -it ubuntu

-d后台运行,–name给容器起名

1
sudo docker run -t -d --name archtry archlinux

查看运行中的container

1
docker ps

查看所有的container,包括停止的

1
docker ps -a

Start one or more stopped containers

run每次会根据image创建一个新的container,对于已有的container之后每次启动应该用start,而非再用同样的image去run,docker run最好理解为创建容器的命令

1
docker start CONTAINER_NAME/ID

You can restart a stopped container with all its previous changes intact using docker start. Use docker ps -a to view a list of all containers, including those that are stopped.

startで运行一个Linux容器,不会像runのように瞬间就exit了,而是会停住,像是run -dみたい

Execute a command in a running container

docker exec一定要先有一个运行中的容器

1
sudo docker run -t -d --name justTest alpine

(run的-d参数: Run container in background and print container ID

-t参数: Allocate a pseudo-TTY,分配一个终端,不然没有prompt)

或者start起个容器 (start才是常态)

1
2
sudo docker exec -d justTest touch /tmp/execWorks
sudo docker exec -it justTest sh

cd到tmp查看,真的有个execWorks文件

这样其实就相当于有了个服务器,可以练习运维基本功了,装nginx,配置文件

终止运行中的容器

1
docker stop CONTAINER_NAME/ID

docker kill也行

停止所有运行中的容器,省得一个个敲了

1
sudo docker stop $(sudo docker ps -q)

Remove one or more containers

1
docker rm CONTAINER_NAME/ID

Remove one or more images

1
docker rmi IMAGE_NAME/ID

Fetch the logs of a container 用来看报错信息

1
docker logs CONTAINER_NAME/ID

trouble shooting

查看运行中容器统计数据(CPU,内存,网络) Display a live stream of container(s) resource usage statistics

1
docker stats

Ctrl + c退出

查看某个容器的更具体信息

1
docker inspect CONTAINER_NAME/ID

以JSON格式返回

Dockerfile & build

试着给我的arxivkids的前端写个Dockerfile (其实还需要.dockerignore忽略掉node_modules)

1
2
3
4
5
6
FROM node:alpine
WORKDIR /usr/app
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]

FROM基于的依赖base

WORKDIR指定(specify)要打包的东西都塞到这个目录里,防止和容器里原有的文件重名冲突

COPY把要打包的东西都复制到容器里,第一个.指的是当前目录,也就是Dockerfile所在的目录,第二个.表示目标路径,它是相对于Docker镜像中的当前工作目录的路径。Docker镜像中的当前工作目录是通过WORKDIR指令设置的

半成品image实例化的intermediate容器会执行RUN的命令,RUN通常用来装依赖。之所以是中间容器,是因为生成的文件目录还要被拷贝回镜像里面,还是属于生成image的阶段。

CMD则是最终image实例化的容器执行的


从Dockerfile构建image

1
docker build -t image_name .

.代表Dockerfile就在当前终端目录

具体参考man docker build

生成的image似乎只能通过docker images查看,不知道被存放在本地的哪里

注意把容器的端口绑定到本机的端口。不然不带-p的话直接浏览器输入127.0.0.1:5173啥都没有的,即使容器已经运行了。

1
sudo docker run -d --name container_name -p 8080:5173 image_name

这样浏览器里访问本机8080端口,本机8080端口请求都绑定到容器的5173端口,容器运行的端口是5173

当然还是一样的端口更おすすめ吧

1
sudo docker run -d --name frontend -p 5173:5173 arxivkids_client

但如果你要起多个容器,它们都用了80端口,那你就可以本机host的端口分别是80,81,82…,但不影响各个容器里面还是80端口

Docker Compose

mkdir个文件夹,cd进去,写docker-compose.yaml

例: Docker Compose will BLOW your MIND!!

1
2
3
4
5
6
7
8
9
10
11
12
version: "3"
services:
website:
image: nginx
ports:
- "8081:80"
restart: always
website2:
image: nginx
ports:
- "8082:80"
restart: always

然后可以不用传统的docker run方式起容器了,尤其是当参数多、起多个同样的容器时,用docker-compose更便捷

1
sudo docker run -itd --name web -p 8080:80 nginx

但注意: docker-compose命令一定要在docker-compose.yaml的目录下执行,不然会报错no configuration file provided

1
2
3
sudo docker-compose up -d	相当于按照.yaml配置のようにdocker run
sudo docker-compose stop
sudo docker-compose down stop并且把容器remove了

参考资料

https://docs.docker.com/ 官方文档

https://docs.docker.com/engine/reference/commandline/run/ 色々命令

https://yeasy.gitbook.io/docker_practice/ ある中文教程

https://wiki.archlinux.org/title/Docker

https://hub.docker.com/ docker hub

https://github.com/docker/awesome-compose docker-compose的例子

  • Title: 230716_再学docker
  • Author: Haoliang Tang
  • Created at : 2023-07-16 00:00:00
  • Updated at : 2023-11-02 20:24:18
  • Link: https://hl-tang.github.io/2023/07/16/230716_再学docker/
  • License: This work is licensed under CC BY-NC-SA 4.0.
 Comments