В хостинге некоторые решения могут показаться вам нестандартными.
Поэтому перед началом работы мы бы рекомендовали ознакомиться с вводной статьей.
В рамках облачного хостинга возможно разместить сайты, написанные на множестве языков программирования.
Ваш сайт может быть написан на C, C++, golang или другом языке программирования.
В рамках этой статьи мы, в качестве примера, запустим простой сайт на golang.
Скачать golang можно на официальном сайте.
Предположим у нас уже есть приложение, которое при запуске прикрепляется (bind) к порту 80.
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r * http.Request) {
fmt.Fprintf(w, "Welcome to the Internet! Please follow me.\n")
})
http.ListenAndServe(":80", nil)
}
При обращении к сайту приложение выводит лишь одну строку текста Welcome to the Internet! Please follow me.
# curl 0.0.0.0:80
Welcome to the Internet! Please follow me.
Если бы мы захотели разместить это приложение на хостинге, то нам бы потребовалось немного его изменить. Прежде всего, на хостинге мы не можем прикрепляется (bind) к порту 80, поскольку он уже занят вебсервером nginx.
Поэтому приложению потребуется прикрепиться на IP и порт, указанные в переменных окружения APP_IP и APP_PORT.
Изменим код нашего приложения таким образом, чтобы прикрепляться к APP_IP и APP_PORT.
Переменные окружения мы будем получать при помощи модуля os
, встроенного в golang.
package main
import (
"os"
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to the Internet! Please follow me.\n")
})
// создадим переменные APP_IP и APP_PORT, а их значения возьмем из одноименных переменных окружения
APP_IP := os.Getenv("APP_IP")
APP_PORT := os.Getenv("APP_PORT")
fmt.Println(APP_IP+":"+APP_PORT)
http.ListenAndServe(APP_IP+":"+APP_PORT, nil)
}
Сохраним этот код в файл welcome.go
.
# ls -l
total 4
-rw-r--r-- 1 root root 629 Sep 4 10:23 welcome.go
Скомпилируем его
# go build welcome.go
# ls -l
total 5564
-rwxr-xr-x 1 root root 5689373 Sep 4 10:25 welcome
-rw-r--r-- 1 root root 629 Sep 4 10:23 welcome.go
Полученный файл welcome
осталось загрузить на хостинг.
Создадим новый сайт на хостинге.
При создании сайта в качестве конфигурации выберите “EXE”:
Для загрузки файла подключитесь к хостингу через FileZilla.
Загрузите файл welcome
в каталог sitename/app
.
После загрузки файла, в FileZilla кликните правой кнопкой на файл и выберите “Права доступа к файлу”.
В поле “Числовое значение” укажите 755
.
Далее откроем панель управления и
перейдем в созданный сайт. Откроем вкладку Python AsyncIO и в строке “APP_PATH” укажем
полный путь до файла. Например /home/c0000/mydomain-async.com/app/welcome
.
Осталось со своего компьютера проверить все ли работает корректно:
user@local-pc:~$ curl http://mydomain-async.com/
Welcome to the Internet! Please follow me.
user@local-pc:~$
Готово!
Если вы планируете отлаживать работу сайта локально, и только потом загружать на хостинг, то достаточно локально создать переменные APP_IP и APP_PORT.
user@local-pc:~$ export APP_PORT=8081
user@local-pc:~$ export APP_IP=127.0.0.1
user@local-pc:~$ env | grep 'APP_'
APP_PORT=8081
APP_IP=127.0.0.1
user@local-pc:~$ ./welcome
127.0.0.1:8081
После этого
user@local-pc:~$ curl 127.0.0.1:8081
Welcome to the Internet! Please follow me.
Одна из сложностей при сборке приложений заключается в том, что приложение успешно собранное и работающее на вашем компьютере может не работать на других. Например приложение собранное в Ubuntu 22.04 из-за разницы в версиях библиотеки glibc может не работать в Debian 9 Stretch. Один из способов позволить приложению корректно запуститься в окружении сервера хостинга - это скомпилировать приложение без использования внешних библиотек.
Рассмотрим детальней полученный на прошлом этапе исполняемый файл
user@local-pc:~$ file welcome
welcome: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=9rzcu_tW7FPaZZ6_MEWj/X7Isq3NKMxj4D8uz87yS/MSlxJelyutuv2Dc8p77R/X1S-Kc6BRngxA1qRrSZG, not stripped
Вывод утилиты file
говорит о том, что исполняемый файл является динамическим. То есть он зависит от наличия и версий библиотек в окружении, где он будет запускаться. При этом он ожидает именно те версии библиотек, которые были доступны на момент сборки приложения, то есть те, что используются в вашей системе.
С помощью утилиты ldd
можно увидеть какие библиотеки требуются для работы исполняемого файла
user@local-pc:~$ ldd welcome
linux-vdso.so.1 (0x00007f42eb35e000)
libc.so.6 => /lib64/libc.so.6 (0x00007f42eb152000)
/lib64/ld-linux-x86-64.so.2 (0x00007f42eb360000)
Поскольку версия библиотек на сервере хостинга и в окружении где производится сборка приложения могут отличаться, предпочтительным является сборка приложения статически, т.е. без использования сторонних библиотек. Это достигается путем указания дополнительных опций при сборке приложения
user@local-pc:~$ go build -tags 'netgo' -ldflags "-s -w -extldflags -static" welcome.go
user@local-pc:~$ file welcome
welcome: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=mfZp2e-AVBGm2ZZWRoD5/wtGxpCfPjcRqCSYJu823/qKgNidYPsL4IF139tWFE/vOqs3bU0lFwPVnIGzzUL, stripped
Из вывода утилиты file
следует, что исполняемый файл собран статически, а это значит, что независимо от окружения в котором он собирался, независимо от версий библиотек, он успешно запустится на сервере хостинга.
Альтернативой сборке статического приложения стоит рассмотреть сборку приложения в docker-контейнере. Идея такого способа в том, что сборка приложения будет производиться в окружении максимально близком к окружению сервера хостинга, что позволит при сборке приложения использовать те же версии библиотек. Данная глава подразуемает, что у вас в системе уже установлен Docker
и у вашего пользователя есть возможность запускать контейнеры без использования утилиты sudo
Для начала нужно определиться в каком окружении будет запускаться ваше приложение. Это можно узнать подключившись к вашему контейнеру по SSH и выполнив команду cat /etc/debian_version
c0000@h0:~$ cat /etc/debian_version
10.12
c1111@h1:~$ cat /etc/debian_version
9.13
Такой вывод говорит о том, что контейнер c0000
использует окружение Debian 10 Buster, а контейнер c1111
Debian 9 Stretch.
Сейчас необходимо перейти в каталог с исходным кодом вашего приложения и выполнить следующие команды
Команда для сборки приложения в контейнере с окружением Debian 9 Stretch:
user@local-pc:~$ docker run --rm -e GO111MODULE=off -v "$PWD":/usr/src/welcome -w /usr/src/welcome netangels/golang-1.18:stretch go build -v
Команда для сборки приложения в контейнере с окружением Debian 10 Buster:
user@local-pc:~$ docker run --rm -e GO111MODULE=off -v "$PWD":/usr/src/welcome -w /usr/src/welcome netangels/golang-1.18:buster go build -v
После этого в каталоге вашего приложения появится исполняемый файл, который вы сможете загрузить в ваш контейнер
user@local-pc:~$ file welcome
welcome: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=irT9CJLwkq1tFmj-BrTH/L-3o73raCE4WYXPHmNCi/lBNEacOmp4jIpOC06D7R/6h30njUA-Xokp6hVEF5P, not stripped
user@local-pc:~$ ldd welcome
linux-vdso.so.1 (0x00007ffe5a55e000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f24ad0c0000)
libc.so.6 => /lib64/libc.so.6 (0x00007f24acecc000)
/lib64/ld-linux-x86-64.so.2 (0x00007f24ad0d9000)