230716_再学docker
原理介绍
为什么需要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 | sudo docker run -t -d --name archtry archlinux |
查看到的内核信息和本机一样
而虚拟机需要各自单独的内核,同时还需要一个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 | docker -v |
启动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://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 | sudo docker exec -d justTest touch /tmp/execWorks |
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 | FROM node:alpine |
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 | version: "3" |
然后可以不用传统的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 | sudo docker-compose up -d 相当于按照.yaml配置のようにdocker run |
参考资料
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.