超详细的docker部署Web应用

使用docker搭建web环境

拉取镜像

$ docker pull ubuntu:18.04

创建容器

创建容器并挂载共享文件夹。

$ docker run -v /run/media/duapple/Data/project:/media/shared -itd --name web_server ubuntu:18.04 /bin/bash

启动镜像

$ docker exec -it web_server /bin/bash

创建普通用户

# useradd -d /home/duapple -m duapple
# passwd duapple

添加用户组

# usermod -g duapple -G root duapple

使用sudo

# apt update 
# apt install sudo vim
# chmod u+w /etc/sudoers
# vim /etc/sudoers

添加

root    ALL=(ALL:ALL) ALL
duapple ALL=(ALL:ALL) ALL
# chmod u-w /etc/sudoers

配置bash

修改该用户的默认shellbash。(不修改会导致很多命令不能用)

# usermod -s /bin/bash duapple

新建 /home/duapple/.bashrc 文件。

#
# ~/.bashrc
#

export PATH=$PATH:/opt/arm-2014.05/bin

[[ $- != *i* ]] && return

colors() {
	local fgc bgc vals seq0

	printf "Color escapes are %s\n" '\e[${value};...;${value}m'
	printf "Values 30..37 are \e[33mforeground colors\e[m\n"
	printf "Values 40..47 are \e[43mbackground colors\e[m\n"
	printf "Value  1 gives a  \e[1mbold-faced look\e[m\n\n"

	# foreground colors
	for fgc in {30..37}; do
		# background colors
		for bgc in {40..47}; do
			fgc=${fgc#37} # white
			bgc=${bgc#40} # black

			vals="${fgc:+$fgc;}${bgc}"
			vals=${vals%%;}

			seq0="${vals:+\e[${vals}m}"
			printf "  %-9s" "${seq0:-(default)}"
			printf " ${seq0}TEXT\e[m"
			printf " \e[${vals:+${vals+$vals;}}1mBOLD\e[m"
		done
		echo; echo
	done
}

[ -r /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion

# Change the window title of X terminals
case ${TERM} in
	xterm*|rxvt*|Eterm*|aterm|kterm|gnome*|interix|konsole*)
		PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/\~}\007"'
		;;
	screen*)
		PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/\~}\033\\"'
		;;
esac

use_color=true

# Set colorful PS1 only on colorful terminals.
# dircolors --print-database uses its own built-in database
# instead of using /etc/DIR_COLORS.  Try to use the external file
# first to take advantage of user additions.  Use internal bash
# globbing instead of external grep binary.
safe_term=${TERM//[^[:alnum:]]/?}   # sanitize TERM
match_lhs=""
[[ -f ~/.dir_colors   ]] && match_lhs="${match_lhs}$(<~/.dir_colors)"
[[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(</etc/DIR_COLORS)"
[[ -z ${match_lhs}    ]] \
	&& type -P dircolors >/dev/null \
	&& match_lhs=$(dircolors --print-database)
[[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true

if ${use_color} ; then
	# Enable colors for ls, etc.  Prefer ~/.dir_colors #64489
	if type -P dircolors >/dev/null ; then
		if [[ -f ~/.dir_colors ]] ; then
			eval $(dircolors -b ~/.dir_colors)
		elif [[ -f /etc/DIR_COLORS ]] ; then
			eval $(dircolors -b /etc/DIR_COLORS)
		fi
	fi

	if [[ ${EUID} == 0 ]] ; then
		PS1='\[\033[01;31m\][\h\[\033[01;36m\] \W\[\033[01;31m\]]\$\[\033[00m\] '
	else
		PS1='\[\033[01;32m\][\u@\h\[\033[01;37m\] \W\[\033[01;32m\]]\$\[\033[00m\] '
	fi

	alias ls='ls --color=auto'
	alias grep='grep --colour=auto'
	alias egrep='egrep --colour=auto'
	alias fgrep='fgrep --colour=auto'
else
	if [[ ${EUID} == 0 ]] ; then
		# show root@ when we don't have colors
		PS1='\u@\h \W \$ '
	else
		PS1='\u@\h \w \$ '
	fi
fi

unset use_color safe_term match_lhs sh

alias cp="cp -i"                          # confirm before overwriting something
alias df='df -h'                          # human-readable sizes
alias free='free -m'                      # show sizes in MB
alias np='nano -w PKGBUILD'
alias more=less
alias proxyyay="ALL_PROXY=socks://localhost:1089 yay "
alias grepf="grep -R -n -s"
alias findc="find . -name \"*.c\" | xargs grep -n -s "
alias findh="find . -name \"*.h\" | xargs grep -n -s "
alias finda="find . -name \"*\" | xargs grep -n -s "
alias rmts="mv -t ~/.mytrash "

xhost +local:root > /dev/null 2>&1

complete -cf sudo

# Bash won't get SIGWINCH if another process is in the foreground.
# Enable checkwinsize so that bash will check the terminal size when
# it regains control.  #65623
# http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11)
shopt -s checkwinsize

shopt -s expand_aliases

# export QT_SELECT=4

# Enable history appending instead of overwriting.  #139609
shopt -s histappend

#
# # ex - archive extractor
# # usage: ex 
ex ()
{
  if [ -f $1 ] ; then
    case $1 in
      *.tar.bz2)   tar xjf $1   ;;
      *.tar.gz)    tar xzf $1   ;;
      *.bz2)       bunzip2 $1   ;;
      *.rar)       unrar x $1     ;;
      *.gz)        gunzip $1    ;;
      *.tar)       tar xf $1    ;;
      *.tbz2)      tar xjf $1   ;;
      *.tgz)       tar xzf $1   ;;
      *.zip)       unzip $1     ;;
      *.Z)         uncompress $1;;
      *.7z)        7z x $1      ;;
      *)           echo "'$1' cannot be extracted via ex()" ;;
    esac
  else
    echo "'$1' is not a valid file"
  fi
}

重启终端或者 source /home/duapple/.bashrc 生效。

系统工具安装

需要编译环境请安装 gcc, make

$ sudo apt install net-tools iputils-ping gcc make

挂载共享文件夹

$ sudo systemctl stop docker 

修改 /var/lib/docker/containers/[容器ID] 下的 config.v2.jsonhostconfig.json 配置文件中对应的挂载选项。修改 /run/media/duapple/Data/project 为我们需要挂载的主机目录。修改成功后,重启docker服务。

{
    "StreamConfig": {},
    "State": {
        "Running": false,
        "Paused": false,
        "Restarting": false,
        "OOMKilled": false,
        "RemovalInProgress": false,
        "Dead": false,
        "Pid": 0,
        "ExitCode": 0,
        "Error": "",
        "StartedAt": "2022-05-07T16:02:38.36826019Z",
        "FinishedAt": "2022-05-07T16:04:10.879309771Z",
        "Health": null
    },
    "ID": "92788eda9c8d03533096a0387d39097626c2223bef6bf37b16d9642340743195",
    "Created": "2022-05-06T14:18:07.32273477Z",
    "Managed": false,
    "Path": "/bin/bash",
    "Args": [],
    "Config": {
        "Hostname": "92788eda9c8d",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "Tty": true,
        "OpenStdin": true,
        "StdinOnce": false,
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "Cmd": [
            "/bin/bash"
        ],
        "Image": "ubuntu:18.04",
        "Volumes": null,
        "WorkingDir": "",
        "Entrypoint": null,
        "OnBuild": null,
        "Labels": {}
    },
    "Image": "sha256:c6ad7e71ba7d4969784c76f57c4cc9083aa96bb969d802f2ea38f4aaed90ff93",
    "NetworkSettings": {
        "Bridge": "",
        "SandboxID": "2a9c29965b238576d16aeea8e4c02b838664a016220f198f22639c58a4236445",
        "HairpinMode": false,
        "LinkLocalIPv6Address": "",
        "LinkLocalIPv6PrefixLen": 0,
        "Networks": {
            "bridge": {
                "IPAMConfig": null,
                "Links": null,
                "Aliases": null,
                "NetworkID": "2d8b901aba177354671a1b494bcba27559f5ec7d390a8adf37fff3129695d280",
                "EndpointID": "",
                "Gateway": "",
                "IPAddress": "",
                "IPPrefixLen": 0,
                "IPv6Gateway": "",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "MacAddress": "",
                "DriverOpts": null,
                "IPAMOperational": false
            }
        },
        "Service": null,
        "Ports": null,
        "SandboxKey": "/var/run/docker/netns/2a9c29965b23",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null,
        "IsAnonymousEndpoint": false,
        "HasSwarmEndpoint": false
    },
    "LogPath": "/var/lib/docker/containers/92788eda9c8d03533096a0387d39097626c2223bef6bf37b16d9642340743195/92788eda9c8d03533096a0387d39097626c2223bef6bf37b16d9642340743195-json.log",
    "Name": "/web_server",
    "Driver": "overlay2",
    "OS": "linux",
    "MountLabel": "",
    "ProcessLabel": "",
    "RestartCount": 0,
    "HasBeenStartedBefore": true,
    "HasBeenManuallyStopped": true,
    "MountPoints": {
        "/media/shared": {
            "Source": "/run/media/duapple/Data/project",
            "Destination": "/media/shared",
            "RW": true,
            "Name": "",
            "Driver": "",
            "Type": "bind",
            "Propagation": "rprivate",
            "Spec": {
                "Type": "bind",
                "Source": "/run/media/duapple/Data/project",
                "Target": "/media/shared"
            },
            "SkipMountpointCreation": false
        }
    },
    "SecretReferences": null,
    "ConfigReferences": null,
    "AppArmorProfile": "docker-default",
    "HostnamePath": "/var/lib/docker/containers/92788eda9c8d03533096a0387d39097626c2223bef6bf37b16d9642340743195/hostname",
    "HostsPath": "/var/lib/docker/containers/92788eda9c8d03533096a0387d39097626c2223bef6bf37b16d9642340743195/hosts",
    "ShmPath": "",
    "ResolvConfPath": "/var/lib/docker/containers/92788eda9c8d03533096a0387d39097626c2223bef6bf37b16d9642340743195/resolv.conf",
    "SeccompProfile": "",
    "NoNewPrivileges": false,
    "LocalLogCacheMeta": {
        "HaveNotifyEnabled": false
    }
}
{
    "Binds": [
        "/run/media/duapple/Data/project:/media/shared"
    ],
    "ContainerIDFile": "",
    "LogConfig": {
        "Type": "json-file",
        "Config": {}
    },
    "NetworkMode": "default",
    "PortBindings": {},
    "RestartPolicy": {
        "Name": "no",
        "MaximumRetryCount": 0
    },
    "AutoRemove": false,
    "VolumeDriver": "",
    "VolumesFrom": null,
    "CapAdd": null,
    "CapDrop": null,
    "CgroupnsMode": "private",
    "Dns": [],
    "DnsOptions": [],
    "DnsSearch": [],
    "ExtraHosts": null,
    "GroupAdd": null,
    "IpcMode": "private",
    "Cgroup": "",
    "Links": null,
    "OomScoreAdj": 0,
    "PidMode": "",
    "Privileged": false,
    "PublishAllPorts": false,
    "ReadonlyRootfs": false,
    "SecurityOpt": null,
    "UTSMode": "",
    "UsernsMode": "",
    "ShmSize": 67108864,
    "Runtime": "runc",
    "ConsoleSize": [
        0,
        0
    ],
    "Isolation": "",
    "CpuShares": 0,
    "Memory": 0,
    "NanoCpus": 0,
    "CgroupParent": "",
    "BlkioWeight": 0,
    "BlkioWeightDevice": [],
    "BlkioDeviceReadBps": null,
    "BlkioDeviceWriteBps": null,
    "BlkioDeviceReadIOps": null,
    "BlkioDeviceWriteIOps": null,
    "CpuPeriod": 0,
    "CpuQuota": 0,
    "CpuRealtimePeriod": 0,
    "CpuRealtimeRuntime": 0,
    "CpusetCpus": "",
    "CpusetMems": "",
    "Devices": [],
    "DeviceCgroupRules": null,
    "DeviceRequests": null,
    "KernelMemory": 0,
    "KernelMemoryTCP": 0,
    "MemoryReservation": 0,
    "MemorySwap": 0,
    "MemorySwappiness": null,
    "OomKillDisable": null,
    "PidsLimit": null,
    "Ulimits": null,
    "CpuCount": 0,
    "CpuPercent": 0,
    "IOMaximumIOps": 0,
    "IOMaximumBandwidth": 0,
    "MaskedPaths": [
        "/proc/asound",
        "/proc/acpi",
        "/proc/kcore",
        "/proc/keys",
        "/proc/latency_stats",
        "/proc/timer_list",
        "/proc/timer_stats",
        "/proc/sched_debug",
        "/proc/scsi",
        "/sys/firmware"
    ],
    "ReadonlyPaths": [
        "/proc/bus",
        "/proc/fs",
        "/proc/irq",
        "/proc/sys",
        "/proc/sysrq-trigger"
    ]
}

修改 "Privileged": true,,使容器获得真正的root权限,否则挂载网络共享文件夹会失败。

重启服务。

$ systemctl start docker.service

挂载网络文件夹

也需要运行参数 "Privileged": true,

$ sudo apt install nfs-common
$ sudo mount -t nfs4 -o nolock 172.17.0.1:/home/duapple/share /home/duapple/shared/

配置MQTT服务器

安装。

$ sudo apt install mosquitto mosquitto-clients
$ sudo service mosquitto start

测试。

$ mosquitto_sub -h localhost -t test
$ mosquitto_pub -h localhost -t test -m "helloworld"

配置密码。

$ sudo mosquitto_passwd -c /etc/mosquitto/passwd monitor_client
$ sudo vim /etc/mosquitto/conf.d/default.conf

添加:

allow_anonymous false
password_file /etc/mosquitto/passwd

重启docker容器。

重启mosquitto。

$ sudo mosquitto -c /etc/mosquitto/mosquitto.conf
$ sudo service mosquitto restart

如果不加 -u -P 参数,即用户参数鉴权参数,将导致一下错误。

Connection Refused: not authorised.
Error: The connection was refused.

配置端口映射

需要将主机的端口映射到docker容器,其中包含我们应用需要使用到的。Web端口,RTMP端口,MQTT端口。

hostconfig.jsonconfig.v2.json中进行配置。

参考:https://cloud.tencent.com/developer/article/1833131

$ sudo systemctl stop docker.service
# kate /var/lib/docker/containers/92788eda9c8d03533096a0387d39097626c2223bef6bf37b16d9642340743195/hostconfig.json
# kate /var/lib/docker/containers/92788eda9c8d03533096a0387d39097626c2223bef6bf37b16d9642340743195/config.v2.json

修改 hostconfig.json 文件的 PortBindings 参数,如下:

"PortBindings":{"1883/tcp":[{"HostIp":"","HostPort":"1883"}],"1935/tcp":[{"HostIp":"","HostPort":"1935"}],"80/tcp":[{"HostIp":"","HostPort":"80"}],"8080/tcp":[{"HostIp":"","HostPort":"8000"}]}

修改 config.v2.json ,在 "AttachStderr":false, 参数后添加如下参数,与hostconfig.json中的设置对应:

"ExposedPorts":{"1883/tcp":{},"1935/tcp":{},"80/tcp":{},"8080/tcp":{}}

重启docker,当上述参数修改的格式不对时,将导致docker容器启动失败。

$ sudo systemctl start docker.service
$ docker start web_server

在容器中启动nginx后,再在主机浏览器访问localhost:80,即可验证端口映射是否修改成功。

注意:当没有关闭docker服务,就修改配置,会导致配置修改无效。

Nginx配置

编译配置好nginx。

解压 nginx-1.18.0.tar.gznginx-http-flv-module.tar.gz 到同一路径。

$ sudo apt install openssl pcre-devel openssl openssl-devel libpcre3 libpcre3-dev libssl-dev zlib1g-dev
$ cd nginx-1.18.0
$ ./configure --prefix=/usr/local/nginx --add-module=$(pwd)/../nginx-http-flv-module
$ make -j12 
$ sudo make install 
$ sudo ln -s /usr/local/nginx/sbin/nginx /usr/bin/
$ sudo nginx -c /usr/local/nginx/conf/nginx.conf
$ sudo nginx -s reload
$ sudo nginx -t 

修改 /usr/local/nginx/conf/nginx.conf 配置。并拷贝 stat.xsl 到指定位置 /var/www/rtmp

$ sudo cp nginx-http-flv-module/stat.xsl /usr/www/rtmp

配置教程:https://beego.vip/docs/deploy/nginx.md

部署

将上述配置好的容器打包程docker镜像,在服务器上导入。

服务器安装docker。

$ curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
$ docker -h 

配置docker不使用sudo:https://blog.csdn.net/boling_cavalry/article/details/106590784

打包本地主机的docker镜像,并上传到云服务器。

$ docker export web_server -o ubuntu1804_webserver.tar

导入docker镜像。

$ cat ubuntu1804_webserver.tar |docker import - ubuntu1804

创建docker容器。

$ docker run -p 80:80 -p 8080:8080 -p 1935:1935 -p 1883:1883 
--privileged=true -v /home/ubuntu/shared:/home/duapple/shared -itd --name web_server ubuntu1804 /bin/bash
$ docker exec -it web_server su - duapple

在容器中启动nginx和应用即可正常访问。

docker ubuntu使用systemctl

需要设置第一个启动的进程为 /sbin/init ,修改 config.v2.json 中的 /bin/bash/sbin/init ,需要先关闭docker服务。容器内需要安装 systemd

以下为执行成功。

$ [duapple@cef5d671d63d ~]$ sudo systemctl enable mosquitto
[sudo] password for duapple: 
mosquitto.service is not a native service, redirecting to systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable mosquitto

添加自定义服务,在 /lib/systemd/system 下新建 monitor_server.service 文件。添加如下内容:

[Unit]
Description=monitor_server

[Service]
Type=simple
ExecStart=/home/duapple/app/monitor_server/monitor_server
Restart=on-failure
RestartSec=20s
WorkingDirectory=/home/duapple/app/monitor_server

[Install]
WantedBy=multi-user.target

生效配置,设置开机启动并启动web应用。

$ sudo systemctl daemon-reload
$ sudo systemctl enable monitor_server
$ sudo systemctl start monitor_server

完成,可以访问了 : )

你可能感兴趣的:(Ubuntu,Web,Docker,docker,linux,bash)