After the blog website is developed, the last step is to deploy the blog website to the public network server and provide domain name access. The blog website that can be searched through the search engine is the real blog website.
Hello everyone, I am a lone duck of falling xia. After several weeks of hard work, we have finished the development of the blog. In this chapter we begin to deploy the blog site and access our blog site through a public network server and domain name.
First, preparation
In order for our website to be accessible by domain name, we need to have several conditions:
- To buy cloud server, you can choose to buy Ali, Tencent, Huawei and Baidu. Each platform has its own special discount, so you can choose a suitable platform for yourself.
- Install the operating system (OS) of the server. Generally, the server uses Linux, Ubuntu, Cent OS, and Debian
- To buy a domain name, you can use the domain name on the cloud server provider’s platform,
.cn
和.com
Will do. - Purchase a domain name certificate. Only after a domain name certificate is obtained, the browser will not prompt you with security problems when you access the domain name.
- At present, there are two registration procedures for websites, one of which is ICP filing on the platform of the Ministry of Industry and Information Technology. After passing this filing, the public security Network filing needs to be completed.
Second, website deployment
After completing the preparatory work, we officially began to deploy our website.
2.1 the Python
Since our back-end code is written in Python, we need to install the Python runtime environment when we deploy it on the server.
The installation method here, I use the official website tutorial, version 3.7. Tutorial address: docs.python.org/zh-cn/3.7/u…
After the installation is complete, run the following command on the CLI to verify the installation
python -V
pip -V
Copy the code
2.2 Code Distribution
2.2.1 Front-end code
2.2.1.1 compilation
Since we are using a front-end written in Vue and TypeScript, we need to compile into native Javascript code before deploying.
Run the following command in the root directory of the front-end code
yarn build
Copy the code
After the execution is completed, the dist folder will be generated under the code path, which contains the compiled code. The file structure is shown as follows
2.2.1.2 upload
On the server, under the Home directory, create a folder “blog” and create “frontend” under “blog”.
cd ~
mkdir blog
cd blog
mkdir frontend
Copy the code
Then upload the front-end files in the local dist folder to the ~/blog/frontend path by FTP tool, and the front-end code is published.
2.2.2 Back-end code
Since Python is a scripting language, the code itself does not need to be compiled. You can simply upload the source code to the corresponding path on the server.
2.2.2.1 Dependent Installation
Python runs on a server that uses UWSGi, so you need to install dependencies on the server and run the following command
pip install uwsgi
Copy the code
After the installation, run commands to check whether the installation is successful
uwsgi --version
Copy the code
2.2.2.2 writeuwsgi
The configuration file
Create a file uwsgi.ini in the path of the back-end code project. We connect the back-end interface through socket and configure the following information:
[uwsgi]
socket = 127.0.0.1:8000
You can understand the absolute path to this file
chdir = ~/blog/backend/
# wsgi relative to chdir
wsgi-file = project/wsgi.py
processes = 4
# log
daemonize = ~/blog/backend/logs/uwsgi.log
pidfile = ~/blog/backend/uwsgi.pid
master = True
Copy the code
Create a new file uwsgi.param in the back-end code project path with the following contents
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
Copy the code
2.2.2.3 Upload code
In the ~/blog folder of the server, create the Backend folder
cd ~/blog
mkdir backend
Copy the code
Use an FTP tool to upload back-end code to the ~/blog/ Backend folder, including the uwsgi.ini file. In backend, create the logs folder for logging
mkdir logs
Copy the code
At this point, the back-end code is in place.
2.2.2.4 Starting and Stopping back-end services
Start the back-end code with a command
uwsgi --ini ~/blog/backend/uwsgi.ini
Copy the code
The test can view the server logs after startup through log files
tail -f ~/blog/backend/logs/uwsgi.log
Copy the code
The stop command is as follows:
uwsgi --stop ~/blog/backend/uwsgi.pid
Copy the code
If the back-end code is updated later, you need to stop the UWSGi service before starting the code update.
2.3 Nginx
In the current website deployment, Nginx as a reverse proxy server deployment site is the mainstream operation, has been a mature website deployment scheme.
Nginx has the following functions in web site deployment:
- Reverse proxy enables clients on the Internet to access the capabilities and data provided by the Intranet server.
- Load balancing to share the load of back-end servers
- HTTP server, Nginx itself is also a static resource server, and in the process of static resource request and response, better than the old Web server, better performance. Nginx enables the separation of dynamic and static deployment.
2.3.1 installation
There are a lot of tutorials on the Internet, so I will provide a reference tutorial for the installation of nginx under Linux.
2.3.2 Certificate File
In the preceding preparations, the domain name certificate is mentioned. In this case, download the certificate file provided by the domain name certificate provider platform, decompress it, and upload the Nginx certificate to the conf file in the Nginx installation path on the server.
2.3.3 Configuration Description
The Nginx configuration file is stored in the conf folder of the Nginx installation directory. The name of the Nginx configuration file is nginx.conf.
2.3.3.1 Static File Proxy
There are two parts of the static file, one is the front-end code file and the other is the media file obtained through the upload interface
location / {
root ~/blog/frontend/dist;
index index.html index.htm;
if(! -e $request_filename) {rewrite^ / (. *) /index.html last; break; }}location /upload/ {
root ~/blog/backend/;
expires 24h;
}
Copy the code
2.3.3.2 Back-end interface proxy
There is critical in the location of two lines of configuration and include uwsgi_pass blog ~ / blog/backend/uwsgi param, clear is the way through the uwsgi agent Python interface
# server
upstream blog{
server 127.0.0.1:8000;
}
location /api/ {
uwsgi_pass blog;
include ~/blog/backend/uwsgi.param;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header accept-encodeing 'gzip, deflate';
proxy_set_header content-type 'application/json';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header authorization $http_authorization;
proxy_set_header accept '* / *';
proxy_set_header x-bce-date $http_x_bce_date;
}
Copy the code
2.3.3.3 Static FilesGzip
The compression
The reason for configuring Gzip compression is that a lot of content needs to be loaded on the first screen of a website when the front and back ends are separated. Therefore, you can reduce the file size during network transmission to speed up the loading of static files during the rendering of the first screen.
# Gzip
gzip on;
gzip_min_length 1k;
gzip_comp_level 3;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
gzip_buffers 32 4k;
gzip_http_version 1.0;
Copy the code
2.3.3.3 Domain Name Configuration
server {
listen 80;
server_name www.longair.cn;
rewrite^ (. *) $ https://${server_name}The $1 permanent;
}
server {
listen 443 ssl;
server_name www.longair.cn;
root html;
index index.html index.htm;
}
Copy the code
2.3.3.3 Https
Certificate File Configuration
ssl_certificate /etc/nginx/longair.cn_nginx/server.crt;
ssl_certificate_key /etc/nginx/longair.cn_nginx/server.key;
ssl_session_timeout 5m;
ssl_ciphersECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:! NULL:! aNULL:! MD5:! ADH:! RC4;ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
Copy the code
2.3.3.3 Http
Automatic transferHttps
When accessing port 80, redirect to port 433.
server {
listen 80;
server_name www.longair.cn;
rewrite^ (. *) $ https://${server_name}The $1 permanent;
}
Copy the code
2.3.3.3 Blog post details jump 404 Problem Configuration
Because we use Vue frame of the front end of the code, routing model USES is the history, the pattern of routing readable, but the article details page routing if, by means of a new page will appear 404 problem, so we need to do processing in this case, configuration principle is that the access path if it’s not the end of file, The page is automatically redirected to the home page. After entering index. HTML, you can change the route to enter the single-page application route, thus correctly rendering the details page. Vue – the router’s website documents: HTML 5 History model | Vue router (vuejs.org)
location / {
root ~/blog/frontend/dist;
index index.html index.htm;
if(! -e $request_filename) {rewrite^ / (. *) /index.html last; break; }}Copy the code
2.3.4 Complete Configuration
The complete configuration is as follows:
user root;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
keepalive_timeout 65;
client_max_body_size 200M;
# Gzip
gzip on;
gzip_min_length 1k;
gzip_comp_level 3;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
gzip_buffers 32 4k;
gzip_http_version 1.0;
# server
upstream blog{
server 127.0.0.1:8000;
}
# blog http
server {
listen 80;
server_name www.longair.cn;
rewrite^ (. *) $ https://${server_name}The $1 permanent;
}
server {
listen* :80;
listen* :443 ssl;
listen[: :] :80;
listen[: :] :443 ssl;
server_name longair.cn;
ssl_certificate /etc/nginx/longair.cn_nginx/server.crt;
ssl_certificate_key /etc/nginx/longair.cn_nginx/server.key;
return 301 https://www.longair.cn$request_uri;
}
# blog https
server {
listen 443 ssl;
server_name www.longair.cn;
root html;
index index.html index.htm;
ssl_certificate /etc/nginx/longair.cn_nginx/server.crt;
ssl_certificate_key /etc/nginx/longair.cn_nginx/server.key;
ssl_session_timeout 5m;
ssl_ciphersECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:! NULL:! aNULL:! MD5:! ADH:! RC4;ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
root ~/blog/frontend/dist;
index index.html index.htm;
if(! -e $request_filename) {rewrite^ / (. *) /index.html last; break; }}location /upload/ {
root /blog/backend/;
expires 24h;
}
location /api/ {
uwsgi_pass blog;
include ~/blog/backend/uwsgi.param;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header accept-encodeing 'gzip, deflate';
proxy_set_header content-type 'application/json';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header authorization $http_authorization;
proxy_set_header accept '* / *';
proxy_set_header x-bce-date $http_x_bce_date;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location = /50x.html {
root~/blog/frontend/dist; }}}Copy the code
Three, the maintenance of the website
3.1 Nginx maintenance
3.1.1 Start Commands
/usr/local/nginx/sbin/nginx -s start
Copy the code
3.1.2 Stop Command
/usr/local/nginx/sbin/nginx -s stop
Copy the code
3.3.3 Restart Command
/etc/nginx/sbin/nginx -s reload
Copy the code
3.3.4 Log View Commands
tail -f /etc/nginx/logs/access.log
tail -f /etc/nginx/logs/error.log
Copy the code
3.2 Maintenance of UWSGI
3.2.1 Start Commands
uwsgi --ini ~/blog/backend/uwsgi.ini
Copy the code
3.2.2 Stop Command
uwsgi --stop ~/blog/backend/uwsgi.pid
Copy the code
3.3.3 Log View Commands
uwsgi --stop ~/blog/backend/uwsgi.pid
Copy the code
Four, about the database
In the development stage, we use sqLite database is very convenient, but if the website is deployed to the server, then use SQLite will appear a lot of problems, such as data security problems, data update problems, so when we deploy the blog online, we need to switch to Mysql database.
4.1 Mysql
The installation
I use version 5.7, installation operation, please refer to your own operating system installation tutorial on the official website. MySQL :: MySQL 5.7 Reference Manual :: 2 Installing and Upgrading MySQL
4.2 Database Construction
On the server, the database is set up through the command line.
2 the root login
mysql -uroot -p
Copy the code
Then enter your password and press Enter to log in to the database.
4.2.2 Creating a Database
- Creating a database
create database blog character set utf8mb4;
Copy the code
- Create a user
create user 'blog'@The '%' identified by '12345678';
Copy the code
- User empowerment
grant all privileges on blog.* to 'blog'@The '%';
flush privileges;
Copy the code
4.3 Adjusting back-end Configurations
4.3.1 Isolation of production and development environments
In the development stage, through sqLite database, easy to debug, fast access, and production environment, using Mysql will be safer. So we want different database configurations for development and production environments.
Therefore, we use environment variables in the system to determine whether it is production or test, so that the code stays the same and does not need to be adjusted at deployment time.
You also need to adjust the host information that can be accessed.
4.3.2 Database Password Protection
As a result of our code may warehouse management through the code, if it is a lot of the warehouse, can will reveal your own database password, so we here by a single configuration file to record database account information, and then in Python by reading the database account configuration file to obtain information, so as to realize the database password protection.
4.3.3 configuration
4.3.3.1 project/settings.py
ALLOWED_HOSTS = ['www.longair.cn'.'127.0.0.1'.'localhost', ]
ENV_PROFILE = os.getenv("PYTHON_ENV")
if ENV_PROFILE == "production":
import configparser
cf = configparser.ConfigParser()
cf.read('/blog/db.cnf') The contents of this file will be created in the next step, as long as the file to be created in the next step is in the path written here
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql'.'NAME': cf.get('db'.'database'),
'USER': cf.get('db'.'user'), Get the database user name from the configuration file
'PASSWORD': cf.get('db'.'password'), Get the database password from the configuration file
'HOST': 'localhost'.'PORT': '3306'
}
}
DEBUG = False Disable the debug mode in the production environment
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3'.'NAME': os.path.join(BASE_DIR, 'data/db.sqlite3'),
}
}
DEBUG = True
Copy the code
4.3.3.2 Configuring Environment Variables
To set the environment variables, enter vi ~/. Bashrc and add export PYTHON_ENV=production, press ESC and enter: :wq
Finally, enter source ~/.bashrc
4.3.3.3 Adding the Database Account Configuration File
Add vi db.cnf under ~/blog and add the following:
[db]
database = blog
user = blog
password = 12345678
default-character-set = utf8
Copy the code
The database, account, and password must be consistent with the preceding database information.
Congratulations, your blog site is now deployed and you can access your blog site by domain name.
In the next post, I will summarize the problems and solutions encountered during the entire blog development process.