Данное решение не является решением задачи соревнования. Мы не рекомендуем вам проводить на нём рейтинговый обстрел.
Для примера напишем веб-сервер на языке
Go
, который будет на все запросы отвечать "Hello, I'm Web Server!".
Для этого создадим файл
main.go
, в котором напишем:
package main
import "net/http"
func DumbHandler(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("Hello, I'm Web Server!"))
}
func main () {
http.HandleFunc("/", DumbHandler)
http.ListenAndServe(":80", nil)
}
Этого вполне достаточно для нашего простого решения.
Теперь скомпилируем, соберем и запустим наш сервер. Для этого не нужно ничего устанавливать, кроме
Docker
.
Чтобы создать свой Docker-container, нам нужен файл с названием
Dockerfile
. Создадим его в папке, в которой находитсяmain.go
. ВDockerfile
находятся директивы, которые выполняются при сборке контейнера. Он, фактически, описывает состояние системы перед запуском.
Любой
Dockerfile
можно наследовать от другогоDockerfile
, и в нашем случае мы отнаследуемся от файла, который описывает базовую CentOS 7. Нам надо скачать и установитьGo
, скомпилировать нашmain.go
и запустить сервер. Сделать это можно так:
# Наследуемся от CentOS 7
FROM centos:7
# Выбираем рабочую папку
WORKDIR /root
# Устанавливаем wget и скачиваем Go
RUN yum install -y wget && \
wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
# Устанавливаем Go, создаем workspace и папку проекта
RUN tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz && \
mkdir go && mkdir go/src && mkdir go/bin && mkdir go/pkg && \
mkdir go/src/dumb
# Задаем переменные окружения для работы Go
ENV PATH=${PATH}:/usr/local/go/bin GOROOT=/usr/local/go GOPATH=/root/go
# Копируем наш исходный main.go внутрь контейнера, в папку go/src/dumb
ADD main.go go/src/dumb
# Компилируем и устанавливаем наш сервер
RUN go build dumb && go install dumb
# Открываем 80-й порт наружу
EXPOSE 80
# Запускаем наш сервер
CMD ./go/bin/dumb
Запуск сервера должен происходить не на этапе сборки, а на этапе запуска контейнера, поэтому мы используем директиву
CMD
. Теперь мы можем собрать контейнер с помощью Docker. Находясь в папке с Dockerfile, надо запустить в консоли:
$ docker build -t dumb .
-t dumb
добавляет контейнеру тэг, по которому в дальнейшем мы будем к нему обращаться.
Контейнер соберется, и выведет в консоль все, что выдадут команды из
Dockerfile
при выполнении. Теперь убедимся, что все работает правильно, запустив контейнер локально. Нам надо связать порт в контейнере с портом на реальной машине.
$ docker run --rm -p 8080:80 -t dumb
-p 8080:80
перенаправит запросы к 8080 порту нашей машины на 80 порт контейнера.
-t dumb
- обращение к контейнеру по тэгу, который мы добавили при сборке.
Если зайти в браузере на localhost:8080, то мы увидим "Hello, I'm Web Server!". Именно то, что мы и хотели!
Теперь остался последний шаг - отправить пробное решение на проверку. Для этого надо залогиниться в Docker, проставить свой тэг и, собственно, отправить решение.
$ docker login stor.highloadcup.ru
Username: [email protected] # мой email
Password: 12345678 # мой секретный ключ из личного кабинета
Login Succeeded # на highloadcup.ru
$ docker tag dumb stor.highloadcup.ru/travels/disabled_cat # тут disabled_cat - это мой личный
$ docker push stor.highloadcup.ru/travels/disabled_cat # репозиторий со страницы с задачей
Теперь решение отправлено на проверку. Перейдем на сайт и посмотрим результаты.
Наше решение проходит стадии обстрела.
После окончания пробного обстрела мы видим его статистику.
Рейтинговый обстрел на пробном решении мы запускать, конечно, не будем. Его можно запускать только два раза за двенадцать часов. Подробнее
Резюмируем - теперь мы можем создавать решение, собирать контейнер с ним и отправлять его на проверку в систему. Подробнее
Это как раз все, что нужно, чтоб успешно начать! Далее можно добавлять в
Dockerfile
установку новых компонент (mysql
,memcached
,python
,ruby
...), реализовывать все типы запросов, улучшать производительность, балансировать нагрузку и все, что душе угодно! Желаем удачи!