范文健康探索娱乐情感热点
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

超值一篇分享,Docker从入门到实战过程全记录

  作者 | 天元浪子
  来源 | CSDN博客
  和Docker相关的概念
  想要真正理解Docker,就不得不从虚拟化技术的发展历程说起。普遍认为虚拟化技术经历了物理机时代、虚拟机时代,目前已经进入到了容器化时代。可以说,Docker是虚拟化技术不断发展的必然结果。
  那么,什么是容器呢?容器和虚拟机有什么不同?Docker和容器又是什么关系呢?搞明白这几个问题,Docker的概念就清晰了。
  1.1 虚拟机和容器
  借助于VMWare等软件,可以在一台计算机上创建多个虚拟机,每个虚拟机都拥有独立的操作系统,可以各自独立的运行程序。这种分身术虽然隔离度高(操作系统级),使用方便(类似物理机),但占用存储资源多(GB级)、启动速度慢(分钟级)的缺点也是显而易见的。
  相较于虚拟机,容器(Container)是一种轻量型的虚拟化技术,它虚拟的是最简运行环境(类似于沙盒)而非操作系统,启动速度快(秒级)、占用存储资源少(KB级或MB级),容器间隔离度为进程级。在一台计算机上可以运行上千个容器,这是容器技术对虚拟机的碾压式优势。
  1.2 容器、镜像和Docker
  Docker是一个开源的应用容器引擎,可以创建容器以及基于容器运行的程序。Docker可以让开发者打包他们的应用和依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。
  听起来很简单,但是在Docker和容器之间,还隐藏着一个镜像的概念,令初学者颇感困惑。本质上,Docker镜像是一个特殊的文件系统,它提供容器运行时所需的程序、库、资源、配置等文件。Docker镜像类似于一个py文件,它需要Docker的运行时(类似于Python解释器)运行。镜像被运行时,即创建了一个镜像的实例,一个实例就是一个容器。
  1.3 Docker 和 k8s
  作为容器引擎,Docker为容器化的应用程序提供了开放的标准,使得开发者可以用管理应用程序的方式来管理基础架构,实现快速交付、测试和部署代码。随着容器的大量使用,又产生了如何协调、调度和管理容器的问题,Docker的容器编排应运而生。
  k8s是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理,是一个开源的,用于管理云平台中多个主机上的容器化的应用,k8s的目标是让部署容器化的应用简单并且高效,k8s提供了应用部署、规划、更新、维护的一种机制。
  Docker和k8sr都是以containerd(容器化标准)作为运行时,因此使用Docker创建的镜像完全可以在k8s中无障碍的使用。
  Docker的安装
  2.1 在ubuntu中安装
  在linux系统中安装Docker非常简单,官方为我们提供了一键安装脚本。这个方法也适用于Debian或CentOS等发行版。  curl -sSL https://get.daocloud.io/docker | sh
  安装过程如果出现超时,不要灰心,多试几次,总会成功的。安装完成后,Docker只能被root用户使用,可以使用下面的命令取消权限限制:  sudo gpasswd -a <你的用户名> docker
  然后,重启docker服务:  sudo service docker restart
  最后,关闭当前的命令行,重新打开新的命令行就可以了。
  顺便提一下,如果在CentOS下安装,可能会出现一堆类似于下面的错误:  问题 1: problem with installed package podman-2.0.5-5.module_el8.3.0+512+b3b58dca.x86_64   - package podman-2.0.5-5.module_el8.3.0+512+b3b58dca.x86_64 requires runc >= 1.0.0-57, but none of the providers can be installed   - package podman-3.0.1-6.module_el8.4.0+781+acf4c33b.x86_64 requires runc >= 1.0.0-57, but none of the providers can be installed   - package podman-3.0.1-7.module_el8.4.0+830+8027e1c4.x86_64 requires runc >= 1.0.0-57, but none of the providers can be installed   - package containerd.io-1.4.6-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - cannot install the best candidate for the job   - package runc-1.0.0-64.rc10.module_el8.4.0+522+66908d0c.x86_64 is filtered out by modular filtering   - package runc-1.0.0-65.rc10.module_el8.4.0+819+4afbd1d6.x86_64 is filtered out by modular filtering   - package runc-1.0.0-70.rc92.module_el8.4.0+786+4668b267.x86_64 is filtered out by modular filtering   - package runc-1.0.0-71.rc92.module_el8.4.0+833+9763146c.x86_64 is filtered out by modular filtering  问题 2: package podman-3.0.1-6.module_el8.4.0+781+acf4c33b.x86_64 requires runc >= 1.0.0-57, but none of the providers can be installed   - package containerd.io-1.4.3-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.3-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.3-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - package containerd.io-1.4.3-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - package docker-ce-3:20.10.7-3.el8.x86_64 requires containerd.io >= 1.4.1, but none of the providers can be installed   - package containerd.io-1.4.3-3.2.el8.x86_64 conflicts with runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.3-3.2.el8.x86_64 obsoletes runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.3-3.2.el8.x86_64 conflicts with runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - package containerd.io-1.4.3-3.2.el8.x86_64 obsoletes runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - package podman-catatonit-3.0.1-6.module_el8.4.0+781+acf4c33b.x86_64 requires podman = 3.0.1-6.module_el8.4.0+781+acf4c33b, but none of the providers can be installed   - problem with installed package podman-catatonit-2.0.5-5.module_el8.3.0+512+b3b58dca.x86_64   - package podman-catatonit-3.0.1-7.module_el8.4.0+830+8027e1c4.x86_64 requires podman = 3.0.1-7.module_el8.4.0+830+8027e1c4, but none of the providers can be installed   - package podman-3.0.1-7.module_el8.4.0+830+8027e1c4.x86_64 requires runc >= 1.0.0-57, but none of the providers can be installed   - package containerd.io-1.4.3-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - package containerd.io-1.4.3-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - package containerd.io-1.4.3-3.2.el8.x86_64 conflicts with runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - package containerd.io-1.4.3-3.2.el8.x86_64 obsoletes runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - package containerd.io-1.4.4-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - package containerd.io-1.4.4-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-68.rc92.module_el8.3.0+475+c50ce30b.x86_64   - cannot install the best candidate for the job   - package runc-1.0.0-64.rc10.module_el8.4.0+522+66908d0c.x86_64 is filtered out by modular filtering   - package runc-1.0.0-65.rc10.module_el8.4.0+819+4afbd1d6.x86_64 is filtered out by modular filtering   - package runc-1.0.0-70.rc92.module_el8.4.0+786+4668b267.x86_64 is filtered out by modular filtering   - package runc-1.0.0-71.rc92.module_el8.4.0+833+9763146c.x86_64 is filtered out by modular filtering   - package containerd.io-1.4.4-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.4-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.4-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - package containerd.io-1.4.4-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-70.rc92.module_el8.4.0+673+eabfc99d.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 conflicts with runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - package containerd.io-1.4.6-3.1.el8.x86_64 obsoletes runc provided by runc-1.0.0-73.rc93.module_el8.4.0+830+8027e1c4.x86_64   - package podman-catatonit-2.0.5-5.module_el8.3.0+512+b3b58dca.x86_64 requires podman = 2.0.5-5.module_el8.3.0+512+b3b58dca, but none of the providers can be installed   - package podman-2.0.5-5.module_el8.3.0+512+b3b58dca.x86_64 requires runc >= 1.0.0-57, but none of the providers can be installed
  这是由于docker和Podman冲突造成的,需要先卸载Podman:  yum erase podman buildah
  2.2 在Win10中安装
  Docker的运行,依赖linux的环境,官方提供了Docker Desktop for Windows,但是它需要安装Hyper-V,Hyper-V是微软开发的虚拟机,类似于 VMWare 或 VirtualBox,仅适用于 Windows 10。这个虚拟机一旦启用,QEMU、VirtualBox 或 VMWare Workstation 15 及以下版本将无法使用!如果你必须在电脑上使用其他虚拟机(例如开发 Android 应用必须使用的模拟器),请不要使用 Hyper-V!
  我的电脑是win10家庭版,不能直接安装hyper-v,需要将下面的命令保存到cmd文件中:  pushd "%~dp0" dir /b %SystemRoot%servicingPackages*Hyper-V*.mum >hyper-v.txt for /f %%i in ("findstr /i . hyper-v.txt 2^>nul") do dism /online /norestart /add-package:"%SystemRoot%servicingPackages%%i" del hyper-v.txt Dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /ALL
  然后在cmd文件上点击右键,选择使用管理员运行。执行完毕后会重启,在重启的过程中进行安装。
  2.3 Hello world
  docker服务启动的情况下,运行下面的命令:  docker run ubuntu:20.04 /bin/echo "Hello world"
  此命令的含义是:  docker run:运行docker镜像命令  ubuntu:20.04:镜像名称为ubuntu版本号为20.04  /bin/echo "Hello world":运行参数,此镜像的参数含义为运行镜像的echo命令显示hello world
  第一次运行时,因为本地没有ubuntu:20.04镜像,docker会自动从镜像服务器下载。下载过程可能需要多试几次,只要成功一次,以后执行就不再需要下载了。
  docker官方还提供了一个hello-world镜像,可以直接运行:  docker run hello-world
  此命令省略了镜像版本和运行参数,docker使用latest作为版本,即最新版本。
  从hello world的例子中,也可以体验到,docker实例的运行是非常快的。
  Docker镜像的使用
  docker官方的镜像库比较慢,在进行镜像操作之前,需要将镜像源设置为国内的站点。
  新建文件/etc/docker/daemon.json,输入如下内容:  {     "registry-mirrors" : [         "https://registry.docker-cn.com",         "https://docker.mirrors.ustc.edu.cn",         "http://hub-mirror.c.163.com",         "https://cr.console.aliyun.com/"     ] }
  然后重启docker的服务:  systemctl restart docker
  3.1 列出本地所有镜像
  执行命令 docker images 可以查看  $ docker images REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE ubuntu              20.04               f643c72bc252        5 weeks ago         72.9MB hello-world         latest              bf756fb1ae65        12 months ago       13.3kB
  当前我本地只有刚才安装的两个镜像。
  3.2 从镜像库中查找镜像
  执行命令 docker search 镜像名称可以从docker镜像库中查找镜像。  $ docker search python NAME                             DESCRIPTION                                     STARS              OFFICIAL          AUTOMATED python                           Python is an interpreted, interactive, objec…   5757                [OK]                 django                           Django is a free web application framework, …   1039                [OK]                 pypy                             PyPy is a fast, compliant alternative implem…   260                 [OK]                 joyzoursky/python-chromedriver   Python with Chromedriver, for running automa…   57                                      [OK] nikolaik/python-nodejs           Python with Node.js                             57                                      [OK] arm32v7/python                   Python is an interpreted, interactive, objec…   53                                       circleci/python                  Python is an interpreted, interactive, objec…   42                                       centos/python-35-centos7         Platform for building and running Python 3.5…   38                                       centos/python-36-centos7         Platform for building and running Python 3.6…   30                                       hylang                           Hy is a Lisp dialect that translates express…   29                  [OK]                 arm64v8/python                   Python is an interpreted, interactive, objec…   24                                       revolutionsystems/python         Optimized Python Images                         18                                       centos/python-27-centos7         Platform for building and running Python 2.7…   17                                       bitnami/python                   Bitnami Python Docker Image                     10                                      [OK] publicisworldwide/python-conda   Basic Python environments with Conda.           6                                       [OK] d3fk/python_in_bottle            Simple python:alpine completed by Bottle+Req…   5                                       [OK] dockershelf/python               Repository for docker images of Python. Test…   5                                       [OK] clearlinux/python                Python programming interpreted language with…   4                                        i386/python                      Python is an interpreted, interactive, objec…   3                                        ppc64le/python                   Python is an interpreted, interactive, objec…   2                                        centos/python-34-centos7         Platform for building and running Python 3.4…   2                                        amd64/python                     Python is an interpreted, interactive, objec…   1                                        ccitest/python                   CircleCI test images for Python                 0                                       [OK] s390x/python                     Python is an interpreted, interactive, objec…   0                                        saagie/python                    Repo for python jobs                            0
  最好选择官方(OFFICIAL)的镜像,这样的镜像最稳定一些。
  3.3 下载新的镜像
  执行命令docker pull 镜像名称:版本号即可下载新的镜像。  $ docker pull python:3.8 3.8: Pulling from library/python 6c33745f49b4: Pull complete  ef072fc32a84: Pull complete  c0afb8e68e0b: Pull complete  d599c07d28e6: Pull complete  f2ecc74db11a: Pull complete  26856d31ce86: Pull complete  2cd68d824f12: Pull complete  7ea1535f18c3: Pull complete  2bef93d9a76e: Pull complete  Digest: sha256:9079aa8582543494225d2b3a28fce526d9a6b06eb06ce2bac3eeee592fcfc49e Status: Downloaded newer image for python:3.8 docker.io/library/python:3.8
  镜像下载后,就可以使用镜像来创建容器了。
  Docker容器的使用
  4.1 启动容器
  执行命令docker run即可启动容器,也就是创建某个镜像的实例。docker run命令非常复杂,可以先执行一个docker run --help来查看帮助:  $ docker run --help   Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]   Run a command in a new container   Options:       --add-host list                  Add a custom host-to-IP mapping (host:ip)   -a, --attach list                    Attach to STDIN, STDOUT or STDERR       --blkio-weight uint16            Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)       --blkio-weight-device list       Block IO weight (relative device weight) (default [])       --cap-add list                   Add Linux capabilities       --cap-drop list                  Drop Linux capabilities       --cgroup-parent string           Optional parent cgroup for the container       --cidfile string                 Write the container ID to the file       --cpu-period int                 Limit CPU CFS (Completely Fair Scheduler) period       --cpu-quota int                  Limit CPU CFS (Completely Fair Scheduler) quota       --cpu-rt-period int              Limit CPU real-time period in microseconds       --cpu-rt-runtime int             Limit CPU real-time runtime in microseconds   -c, --cpu-shares int                 CPU shares (relative weight)       --cpus decimal                   Number of CPUs       --cpuset-cpus string             CPUs in which to allow execution (0-3, 0,1)       --cpuset-mems string             MEMs in which to allow execution (0-3, 0,1)   -d, --detach                         Run container in background and print container ID       --detach-keys string             Override the key sequence for detaching a container       --device list                    Add a host device to the container       --device-cgroup-rule list        Add a rule to the cgroup allowed devices list       --device-read-bps list           Limit read rate (bytes per second) from a device (default [])       --device-read-iops list          Limit read rate (IO per second) from a device (default [])       --device-write-bps list          Limit write rate (bytes per second) to a device (default [])       --device-write-iops list         Limit write rate (IO per second) to a device (default [])       --disable-content-trust          Skip image verification (default true)       --dns list                       Set custom DNS servers       --dns-option list                Set DNS options       --dns-search list                Set custom DNS search domains       --domainname string              Container NIS domain name       --entrypoint string              Overwrite the default ENTRYPOINT of the image   -e, --env list                       Set environment variables       --env-file list                  Read in a file of environment variables       --expose list                    Expose a port or a range of ports       --gpus gpu-request               GPU devices to add to the container ("all" to pass all GPUs)       --group-add list                 Add additional groups to join       --health-cmd string              Command to run to check health       --health-interval duration       Time between running the check (ms|s|m|h) (default 0s)       --health-retries int             Consecutive failures needed to report unhealthy       --health-start-period duration   Start period for the container to initialize before starting health-retries countdown (ms|s|m|h) (default 0s)       --health-timeout duration        Maximum time to allow one check to run (ms|s|m|h) (default 0s)       --help                           Print usage   -h, --hostname string                Container host name       --init                           Run an init inside the container that forwards signals and reaps processes   -i, --interactive                    Keep STDIN open even if not attached       --ip string                      IPv4 address (e.g., 172.30.100.104)       --ip6 string                     IPv6 address (e.g., 2001:db8::33)       --ipc string                     IPC mode to use       --isolation string               Container isolation technology       --kernel-memory bytes            Kernel memory limit   -l, --label list                     Set meta data on a container       --label-file list                Read in a line delimited file of labels       --link list                      Add link to another container       --link-local-ip list             Container IPv4/IPv6 link-local addresses       --log-driver string              Logging driver for the container       --log-opt list                   Log driver options       --mac-address string             Container MAC address (e.g., 92:d0:c6:0a:29:33)   -m, --memory bytes                   Memory limit       --memory-reservation bytes       Memory soft limit       --memory-swap bytes              Swap limit equal to memory plus swap: "-1" to enable unlimited swap       --memory-swappiness int          Tune container memory swappiness (0 to 100) (default -1)       --mount mount                    Attach a filesystem mount to the container       --name string                    Assign a name to the container       --network network                Connect a container to a network       --network-alias list             Add network-scoped alias for the container       --no-healthcheck                 Disable any container-specified HEALTHCHECK       --oom-kill-disable               Disable OOM Killer       --oom-score-adj int              Tune host"s OOM preferences (-1000 to 1000)       --pid string                     PID namespace to use       --pids-limit int                 Tune container pids limit (set -1 for unlimited)       --platform string                Set platform if server is multi-platform capable       --privileged                     Give extended privileges to this container   -p, --publish list                   Publish a container"s port(s) to the host   -P, --publish-all                    Publish all exposed ports to random ports       --read-only                      Mount the container"s root filesystem as read only       --restart string                 Restart policy to apply when a container exits (default "no")       --rm                             Automatically remove the container when it exits       --runtime string                 Runtime to use for this container       --security-opt list              Security Options       --shm-size bytes                 Size of /dev/shm       --sig-proxy                      Proxy received signals to the process (default true)       --stop-signal string             Signal to stop a container (default "SIGTERM")       --stop-timeout int               Timeout (in seconds) to stop a container       --storage-opt list               Storage driver options for the container       --sysctl map                     Sysctl options (default map[])       --tmpfs list                     Mount a tmpfs directory   -t, --tty                            Allocate a pseudo-TTY       --ulimit ulimit                  Ulimit options (default [])   -u, --user string                    Username or UID (format: [:])       --userns string                  User namespace to use       --uts string                     UTS namespace to use   -v, --volume list                    Bind mount a volume       --volume-driver string           Optional volume driver for the container       --volumes-from list              Mount volumes from the specified container(s)   -w, --workdir string                 Working directory inside the container
  比如我们要执行python的shell,需要添加-it参数,即:docker run -it python:3.8  $ docker run -it python:3.8  Python 3.8.7 (default, Dec 22 2020, 18:46:25)  [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>>
  4.2 将宿主机的文件挂载到容器
  docker容器与宿主机是隔离的,要想让容器内的程序能访问宿主机上的文件,需要通过-v参数将宿主机的文件挂载到容器中。
  比如我们在宿主机上有一个hello.py,可以打印hello,想要在python容器中执行,就需要进行挂载。-v后还需要接两个参数,分别是宿主机的目录和容器内的目录,两者使用:分隔,路径必须都是绝对路径。
  我的hello.py保存在主目录的/docker_test目录中,将这个目录挂载到容器的/docker_test目录,然后在容器内执行python /docker_test/hello.py:  $ docker run -v ~/docker_test:/docker_test python:3.8 python /docker_test/hello.py hello
  4.3 容器的端口映射
  我们修改一下hello.py,创建一个socket服务端,并监听5000端口,当有客户端连接时,打印客户端的地址,先客户端发送hello,然后关闭连接:  import socket   ip_port = ("127.0.0.1", 5000)   sk = socket.socket() sk.bind(ip_port) sk.listen(5)   while True:     print("server waiting...")     conn,addr = sk.accept()     print(addr)     conn.sendall(b"hello ")     conn.close()
  在容器内执行:  docker run -v ~/docker_test:/docker_test python:3.8 python /docker_test/hello.py
  接下来,尝试用telnet命令连接,结果却是失败的。原因是,127.0.0.1是宿主机的ip地址,5000是容器的端口,这与我们的习惯稍微有些不同。事实上,docker的容器是非常轻量的,它并没有自己的网络,要想访问容器的端口,需要进行端口映射,将容器的某端口映射到宿主机的端口,客户端连接时,只要与宿主机的端口进行连接就可以了。
  需要注意的是,上面的代码创建的服务器,无论如何也不可能被客户端连接,因为代码中绑定了127.0.0.1的ip,在容器中运行时,需要绑定所有ip,即0.0.0.0。  import socket   ip_port = ("0.0.0.0", 5000)   sk = socket.socket() sk.bind(ip_port) sk.listen(5)   while True:     print("server waiting...")     conn,addr = sk.accept()     print(addr)     conn.sendall(b"hello ")     conn.close()
  然后,再使用-p参数,-p还需要三个参数,即宿主机的ip地址、宿主机的端口、容器的端口,三者之间使用:分隔。一般的,可以将宿主机的ip地址省略,只写宿主机的端口:容器的端口即可。  docker run -v ~/docker_test:/docker_test -it -p 5001:5000 python:3.8 python /docker_test/hello.py
  这样,就将容器的5000端口映射到了宿主机的5001端口,使用:  telnet 127.0.0.1 5001
  即可与容器中的服务器进行连接。
  4.4 容器管理
  上面的服务运行之后,可以使用docker ps命令,查看运行中的容器:  $ docker ps CONTAINER ID     IMAGE           COMMAND                  CREATED           STATUS         PORTS                    NAMES ec4c86b8a163     python:3.8      "python /docker_test…"   5 seconds ago     Up 4 seconds   0.0.0.0:5000->5000/tcp   eager_wilson
  显示的内容有下面几列:  CONTAINER ID:容器ID  IMAGE:镜像名称和版本  COMMAND:执行的命令  CREATED:容器创建时间  STATUS:容器的状态  PORTS:端口映射  NAMES:容器名
  要想结束容器,可以使用docker kill 容器ID命令。
  自制Docker镜像
  一般而言,当我们的程序开发完成后,会连同程序文件与运行环境一起制作成一个新的镜像。
  要制作镜像,需要编写Dockerfile。DockeFile由多个命令组成,常用的命令有:  FROM:基于某个镜像来制作新的镜像。格式为:FROM 镜像名称:镜像版本。  COPY:从宿主机复制文件,支持?、*等通配符。格式为:COPY 源文件路径 目标文件路径。  ADD:从宿主机添加文件,格式与COPY相同,区别在于当文件为压缩文件时,会解压缩到目标路径。  RUN:在创建新镜像的过程中执行的shell命令。格式为:RUN shell命令行。注意,此shell命令将在容器内执行。  CMD:在容器实例中运行的命令,格式与RUN相同。注意,如果在docker run时指定了命令,将不会执行CMD的内容。  ENTRYPOINT:在容器实例中运行的命令,格式与CMD相同。注意,如果在docker run时指定了命令,该命令会以命令行参数的形式传递到ENTRYPOINT中。  ENV:在容器中创建环境变量,格式为:ENV 变量名值。
  注意,Docker镜像中有一个层的概念,每执行一个RUN命令,就会创建一个层,层过多会导致镜像文件体积增大。尽量在RUN命令中使用&&连接多条shell命令,减少RUN命令的个数,可以有效减小镜像文件的体积。
  5.1 自制显示文本文件内容镜像
  编写cat.py,接收一个文件名,由python读取文件并显示文件的内容:  import os import sys   input = sys.argv[1]   with open(input, "r") as fp:     print(fp.read())
  这个例子比较简单,缩写Dockerfile如下:  FROM python:3.8 WORKDIR /files COPY cat.py /cat.py ENTRYPOINT ["python", "/cat.py"]
  这个Dockerfile的含义是:  以python:3.8为基础镜像  容器启动命令的工作目录为/files,在运行镜像时,需要我们把宿主机的某目录挂载到容器的/files目录  复制cat.py到容器的根目录下  启动时运行python /cat.py命令
  需要说明的是,ENTRYPOINT有两种写法:  ENTRYPOINT python /cat.py ENTRYPOINT ["python", "/cat.py"]
  这里采用第二种写法,是因为我们要在外部给容器传递参数。执行命令编译Docker镜像:  docker build -t cat:1.0 .
  这个命令中,-t的含义是目标,即生成的镜像名为hello,版本号为1.0,别忘了最后那个.,这叫到上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。
  这样,我们的第一个镜像就制作完成了,使用下面的命令执行它:  docker run -it -v ~/docker_test/cat/files:/files cat:1.0 test.txt
  即可看到~/docker_test/cat/files/test.txt的内容。
  5.2 自制web服务器镜像
  我们使用tornado开发一个网站,而python的官方镜像是没有tornado库的,这就需要在制作镜像时进行安装。
  测试的ws.py如下:  import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web   from tornado.options import define, options define("port", default=8000, help="run on the given port", type=int)   class IndexHandler(tornado.web.RequestHandler):     def get(self):         self.write("Hello world")   if __name__ == "__main__":     tornado.options.parse_command_line()     app = tornado.web.Application(handlers=[(r"/", IndexHandler)])     http_server = tornado.httpserver.HTTPServer(app)     http_server.listen(options.port)     tornado.ioloop.IOLoop.instance().start()
  编写Dockerfile文件如下:  FROM python:3.8 WORKDIR /ws COPY ws.py /ws/ws.py RUN pip install tornado CMD python hello.py
  在此我们验证一下CMD与ENTRYPOINT的区别。在Dockerfile所在有目录下执行如下命令:  docker build -t ws:1.0 .
  执行完成后,再使用docker images使用就可以看到生成的镜像了,然后使用下面的命令运行:  docker run -it -p 8000:8000 ws:1.0
  在浏览器中输入宿主机的ip和8000端口,就可以看到页面了。
  在这个例子中,我使用的运行命令是CMD,如果在docker run中指定的其他的命令,此命令就不会被执行,如:  $ docker run -it -p 8000:8000 ws:1.0 python Python 3.8.7 (default, Dec 22 2020, 18:46:25)  [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>>
  此时,容器中被执行的是python命令,而不是我们的服务。在更多情况下,我们希望在docker run命令中为我们的服务传参,而不是覆盖执行命令,那么,我们应该使用ENTRYPOINT而不是CMD:  FROM python:3.8 WORKDIR /ws COPY ws.py /ws/ws.py RUN pip install tornado ENTRYPOINT python ws.py
  上面这种写法,是不支持传递参数的,ENTRYPOINT和CMD还支持另一种写法:  FROM python:3.8 WORKDIR /ws COPY ws.py /ws/ws.py RUN pip install tornado ENTRYPOINT ["python", "ws.py"]
  使用这种写法,docker run命令中的参数才可以传递给hello.py:  docker run -it -p 8000:9000 ws:1.0 --port=9000
  这个命令中,--port=9000被作为参数传递到hello.py中,因此容器内的端口就成了9000。
  在生产环境中运行时,不会使用-it选项,而是使用-d选项,让容器在后台运行:  $ docker run -d -p 8000:9000 ws:1.0 --port=9000 4a2df9b252e2aff6a8853b3a8bf46c0577545764831bb7557b836ddcd85cba70 $ docker ps                                        CONTAINER ID   IMAGE        COMMAND                  CREATED           STATUS            PORTS                    NAMES 4a2df9b252e2   hello:1.0    "python ws.py --p…"   9 seconds ago     Up 8 seconds      0.0.0.0:8000->9000/tcp   elegant_sammet
  这种方式下,即使当前的控制台被关闭,该容器也不会停止。
  5.3 自制apscheduler服务镜像
  接下来,制作一个使用apscheduler编写的服务镜像,代码如下:  import sys import shutil from apscheduler.schedulers.blocking import BlockingScheduler from apscheduler.triggers.cron import CronTrigger   def scan_files():     shutil.copytree(sys[1], sys[2])   scheduler = BlockingScheduler() scheduler.add_job(     scan_files,     trigger=CronTrigger(minute="*"),     misfire_grace_time=30 )
  Dockerfile也是信手拈来:  FROM python:3.8 WORKDIR / COPY sch.py /sch.py RUN pip install apscheduler ENTRYPOINT ["python", "sch.py"]
  生成镜像:  docker build -t sch:1.0 .
  应该可以运行了,文件复制需要两个目录,在运行时,可以使用两次-v来挂载不同的目录:  docker run -d -v ~/docker_test/sch/src:/src -v ~/docker_test/sch/dest:/dest sch:1.0 /src /dest
  多阶段构建压缩镜像体积
  前面用到的官方python镜像大小足足882MB,在这个基础上,再安装用到的第三方库,添加项目需要的图片等资源,大小很容易就超过1个G,这么大的镜像,网络传给客户非常的不方便,因此,减小镜像的体积是非常必要的工作。
  docker hub上有个一python:3.8-alpine镜像,大小只有44.5MB。之所以小,是因为alpine是一个采用了busybox架构的操作系统,一般用于嵌入式应用。我尝试使用这个镜像,发现安装一般的库还好,但如果想安装numpy等就会困难重重,甚至网上都找不到解决方案。
  还是很回到基本的路线上来,主流的操作系统镜像,ubuntu的大小为72.9MB,centos的大小为209MB——这也算是我更喜欢使用ubuntu的一个重要原因吧!使用ubuntu作为基础镜像,安装python后的大小为139MB,再安装pip后的大小一下子上升到了407MB,要是再安装点其他东西,很容易就赶上或超过python官方镜像的大小了。
  看来,寻常路线是很难压缩镜像文件体积了。幸好,还有一条曲线救国的路可走,这就是多阶段构建法。
  多阶段构建的思想其实很简单,先构建一个大而全的镜像,然后只把镜像中有用的部分拿出来,放在一个新的镜像里。在我们的场景下,pip只在构建镜像的过程中需要,而对运行我们的程序却一点用处也没有。我们只需要安装pip,再用pip安装第三方库,然后将第三方库从这个镜像中复制到一个只有python,没有pip的镜像中,这样,pip占用的268MB空间就可以被节省出来了。
  1、在ubuntu镜像的基础上安装python:  FROM ubuntu RUN apt update      && apt install python3
  然后运行:  docker build -t python:3.8-ubuntu .
  这样,就生成了python:3.8-ubuntu镜像。
  2、在python:3.8-ubuntu的基础上安装pip:  FROM python:3.8-ubuntu RUN apt install python3
  然后运行:  docker build -t python:3.8-ubuntu-pip .
  这样,就生成了python:3.8-ubuntu-pip镜像。
  3、多阶段构建目标镜像:  FROM python:3.8-ubuntu-pip RUN pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy FROM python:3.8-ubuntu COPY --from=0 /usr/local/lib/python3.8/dist-packages/ /usr/local/lib/python3.8/dist-packages/
  这个dockerfile需要解释一下了,因为它有两个FROM命令。
  第一个是以python:3.8-ubuntu-pip镜像为基础,安装numpy,当然,在实际应用中,把所有用到的第三方库出写在这里。
  第二个FROM是以FROM python:3.8-ubuntu镜像为基础,将第三方库统统复制过来,COPY命令后的–from=0的意思是从第0阶段进行复制。实际应用中再从上下文中复制程序代码,添加需要的ENTRYPOINT等。
  最后,再运行:  docker build -t project:1.0 .
  这然,用于我们项目的镜像就做好了。比使用官方python镜像构建的版本,小了大约750MB。
  导入镜像到生产环境
  到此,我们的镜像已经制作好了,可是,镜像文件在哪,如何在生产环境下运行呢?
  刚才使用docker images命令时,已经看到了生成的镜像:  $ docker images                           REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE hello               1.0                 01fe19111dc7        59 minutes ago      893MB python              3.8                 f5041c8ae6b1        13 days ago         884MB ubuntu              20.04               f643c72bc252        5 weeks ago         72.9MB hello-world         latest              bf756fb1ae65        12 months ago       13.3kB
  我们可以使用docker save命令将镜像保存到指定的文件中,保存的文件是一个.tar格式的压缩文件:  docker save -o hello.tar hello:1.0
  将hello.tar复制到生产环境的机器上,然后执行导入命令:  docker load -i hello.tar
  就可以使用了。

什么是b2bb2c?哪个平台好?小白问答专栏每天为你解决一个金融理财问题,喜欢欢迎点赞,并转发到朋友圈哦这些高大上的英文简称其实都是电商的商业模式。那他们究竟是啥?又有什么区别呢?在解释他们之前,我们必须了解它的你觉得头条能取代百度吗?至少在目前,今曰头条替代百度的可能性不大。我也是今日头条注册登录的网友。掏心话说,今日头条所具备的功能,感觉和百度尚有一定的距离。百度云集了搜索广告云盘文库解答等等方方面面的诸多功满分100分,你给荣耀V10打多少分?我给95分吧,可以说几乎完美了。拥有麒麟970加上EMUI8。0软硬AI相结合,更好的拍照,更快的快充,AIcamera等等,都让荣耀V10成为人工智能手机领域独一无二的存在。具体华为手机如何删除文件管理里面没用的文件?华为手机受到很多朋友们的喜爱,今天阿饱就给大家带来关于华为清理内存的小技巧!手机使用时间长了,系统的软件不断的在更新,手机用了两三年之后,渐渐的开始变慢了,这时候人们就想要清理清理千元机当中,性价比超高的5G手机是哪款?千元机当中,性价比最高的5G手机是哪款?目前来说,5G手机已经很普及了,一千出头就可以买到许多不错的中端5G手机了,考虑到这位伙伴的需求是千元机,那自然不能整太贵了。目前价格下探到宁波已在开发个人房源自主挂牌功能,预计不久后即可上线!你会撇开中介买卖二手房吗?杭州市住房保障和房产管理局日前在旗下杭州市二手房交易监管服务平台上,上线个人自主挂牌房源功能,引发广泛关注。此举被称作杭州二手房交易去中介化。简单而言,这个功能,可以让二手房房东自苹果手机哪些方面比较好?文小伊评科技作为一个曾经坚定的安卓系统死忠粉,目前我正在使用iPhone12这款手机。在使用苹果手机的过程中,我其实是带着批判性的眼光来看待苹果手机以及IOS系统的,可以理性的不带有没有无灯的耳机?非常适合学生党的入门级蓝牙耳机分享!本文全是干货,是专门写给新手的蓝牙耳机选购攻略,推荐的10款蓝牙耳机也都各有特色,绝对能满足大多数朋友,欢迎mark以便长期浏览。好了,Lets卢克文是中专学历,为什么分析国际大事能力那么厉害?1。中专只是他的第一学历,后期的学习过程你只是不了解而已2。读万卷书,行万里路。读书是很重要,但社会阅历也是自我成长中极为重要的方面3。你所看到的不仅仅是一个人,而是团队的力量,就看到有人说一加8可以闭着眼睛买,有那么好吗?一加的座右铭不将就,一加手机目标用户是追求品质生活的年轻用户,在每个工艺细节都尽量做到最好。一加8可以闭着眼睛买,是有一定道理的。下文具体说一说。一加8的配置屏幕一加8全系采用了A老式80年代电视机什么配件组成?80年代的电视机以黑白电视为主流,一般由电源变压器把市电降到18V左右的交流电,通过整流滤波输出约20V左右的脉动直流电,通过电源电路的调整稳压,分两路输出。一路(即约20V左右)
助听器能不能代买?这样是错误的,千万不能让别人代买助听器!随意买一个助听器是不能解决听力问题的,随意买一个助听器或许还会给你带来新的听力伤害您好!助听器能不能代买?助听器不可以代买!助听器验配必须是从2899跌至2499元,三星屏65WIMX766,骁龙870口碑旗舰仍受青睐回看整个2021年,高端旗舰市场的口碑下滑不少,主要是因为各大厂商被打了一个措手不及,不成熟的芯片工艺搭配不极致的散热,使得手机发热特别严重,反而是面向次旗舰市场开发的骁龙870深6000mAh13GB大内存1698元你心动吗?2022年初到现在,国内已经出现不下十款高端机型,这些手机都有一个共同卖点,几乎都是围绕相机屏幕和性能展开,并且出现了很多超级快充手机,以往66w快充就很快了,现在没有80w快充都仅2999元,骁龙812GB512GB,还有5000mAh大电池,米粉都心动了今年的手机圈内卷相当严重,为了保证产品的竞争优势,主流手机品牌都在搞机海战术,小米OPPOvivo都不例外。预算25003000元,我们可以买到许多性价比相当出色的新旗舰,红米K5小区如何申请新能源充电桩记者万华翼近日,有市民致电市12345政务服务便民热线,询问小区安装新能源充电桩需要什么手续,如何申请安装。据悉,国家电网有限公司明确支持社会资本参与慢充快充等各类电动汽车充换电设电商预售切忌玩套路最近一段时间,电商超长预售问题受到广泛关注,比如,有些消费者称服装预售期太长,衣服收到时,季节都过了。前不久,中消协点名部分网络商家对预售商品设置超长预售期,表示有些网络经营者利用苹果将向配件商收取年费,每年668元,到期前三次提醒,不交就开除5月18日消息,据充电头网报道,近日苹果正式向MFi计划会员收取年费,过期未支付年费的话,MFi计划会员资格将会被终止。根据苹果发出的关于收取MFi年费的邮件显示,MFi计划年费为苹果iOS15。5发布四大新变化,看完决定升不升昨天凌晨,苹果发布了iOS15。5正式版。不得不说,最近苹果倒是蛮勤快的,本次的正式版本跟上一个RC版只间隔了3天,版本号也都是19F77,基本更新的内容也和最后一个测试版一致。经媒体iPhone13Pro将增产千万台二季度为传统手机销售淡季,但是苹果手机凭借强劲销量,竟要大举增产。据韩国媒体TheElec此前披露,苹果公司决定在二季度大幅增产iPhone13Pro系列机型(包括iPhone13卓尔智联2018年度收入大增1。5倍至561。16亿元北京时间3月31日,卓尔智联(2098。HK)发布2018年业绩公告。受益于公司供应链管理及贸易业务收入大增,公司2018年整体收入相当于上年度的逾2。5倍,毛利同比增长超过50。最赚钱公司,坐拥12亿用户每天收入60亿,人们从出生就使用它如果谈到中国哪家企业最赚钱,相信很多人会第一时间想到阿里巴巴华为或者万达集团。但如果上升国家层面的话,这些企业在一家公司面前就显得相形见绌了,而这家公司堪称是中国赚钱最快的企业,它