#docker #go #networking #ubuntu-20.04
#docker #Вперед #сеть #ubuntu-20.04
Вопрос:
Я пытаюсь запустить HTTP-сервер, написанный на Golang внутри контейнера docker, и я продолжаю получать отказ в подключении. Все выполняется внутри виртуальной машины сервера Ubuntu 20.04, работающей на моем компьютере с Windows 10.
Код сервера Go:
package main
import "github.com/lkelly93/scheduler/internal/server"
func main() {
server := server.NewHTTPServer()
server.Start(3000)
}
package server
import (
"context"
"fmt"
"net/http"
)
type HTTPServer interface {
Start(port int) error
Stop() error
}
func NewHTTPServer() HTTPServer {
return amp;httpServer{}
}
type httpServer struct {
server *http.Server
}
func (server *httpServer) Start(port int) error {
serveMux := newServeMux()
server.server = amp;http.Server {
Addr: fmt.Sprintf(":%d", port),
Handler: serveMux,
}
return server.server.ListenAndServe()
}
func (server *httpServer) Stop() error {
return server.server.Shutdown(context.Background())
}
Мой файл Dockerfile:
FROM ubuntu:20.04
RUN apt-get update -y
#Install needed packages
RUN apt-get install software-properties-common -y
RUN apt-get install python3 -y
RUN apt-get update -y
RUN apt-get install python3-pip -y
RUN apt-get install default-jre -y
#Install language dependacies
#Python
RUN pip3 install numpy
#Reduce VM size
# RUN rm -rf /var/lib/apt/lists/*
#Setup working DIRs
RUN mkdir secure
RUN mkdir secure/runner_files
COPY scheduler /secure
WORKDIR /secure
EXPOSE 3000
CMD ["./scheduler"] <-- The go server is compiled into a binary called scheduler
Я создаю данный файл Dockerfile, а затем запускаю:
docker run -d --name scheduler -p 3000:3000 scheduler:latest
Затем я беру адрес контейнера с:
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' scheduler
->172.17.0.2
Наконец, я использую cURL для отправки http-запроса:
curl http://172.17.0.2:3000/execute/python --data '{"Code":"print("Hello")"}'
Я получаю
curl: (7) Failed to connect to 172.17.0.2 port 3000: Connection refused
но должен получать
{"Stdout":"Hellon"}%
Если я запускаю сервер Go на виртуальной машине Ubuntu, у меня нет проблем с вызовом его с моего компьютера Win10, но, похоже, я не могу вызвать сервер Go, когда он существует внутри контейнера docker с компьютера Ubuntu.
Код Go сложнее, чем просто это, но его слишком много, чтобы публиковать все здесь, не стесняйтесь просматривать все репозитории наhttps://github.com/lkelly93/scheduler.
В конечном итоге это будет серверная часть веб-сайта, который я хочу создать, который запускает код. Что-то вроде LeetCode или Repl.it .
Спасибо!
Редактировать:
docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a56a973040f scheduler:latest "./scheduler" 37 seconds ago Up 36 seconds 0.0.0.0:3000->3000/tcp scheduler
журналы контейнера docker 2a56a973040f не выдали выходных данных.
Редактировать 2:
docker run -it --net container:2a56a973040f nicolaka/netshoot ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 4096 *:3000 *:*
Редактировать 3:
После прочтения справочных страниц я обнаружил, что если бы у меня был тег —network =host для моего изображения, а затем запустить.
curl http://localhost:3000/execute/python --data '{"Code":"print("Hello")"}'
Я получаю правильный вывод. Пока это работает, я хотел бы, чтобы несколько образов docker работали параллельно. Поэтому я бы предпочел использовать IP-адрес для их всех. Поэтому я не думаю, что это постоянное исправление.
Комментарии:
1. docker говорит, что ваш сервер находится на 172.17.0.2, но вы, похоже, используете 172.17.0.1
2. Выполнить копирование неправильной команды. Это должно быть 172.17.0.2, я изменю это.
3. Возможно, это проблема сервера, а не проблема docker. Что выводят журналы сервера?
4. Кроме того, вы пробовали обычный старый localhost?
5. @pygeek Я не думаю, что это сервер, потому что у меня нет проблем, когда я запускаю его вне docker.
Ответ №1:
Чтобы исправить это на моем сервере, я установил IP-адрес 0.0.0.0: 4000. Я использую gin, поэтому пример будет выглядеть так:
r := gin.Default()
r.run("0.0.0.0:4000")
После этого я, наконец, смог получить к нему доступ через свой браузер.
Комментарии:
1. Спасатель жизни. Кто знал, что r.run («localhost: 4000») был моей проблемой с самого начала
2. Я поддерживаю это…. вы заслуживаете медали!
3.
r.run(:4000)
также работает
Ответ №2:
Вы опубликовали порт, который перенаправляет порт с хоста docker на контейнер. Поэтому вы хотите подключиться к http://localhost:3000 . Подключение к контейнерному IP может завершиться ошибкой при установке на рабочий стол, поскольку docker запускается внутри виртуальной машины, а эти частные IP-адреса видны только в виртуальной машине.
Если вы работаете docker-machine
(это относится к более старым установкам docker toolbox), вам нужно будет получить IP-адрес виртуальной машины. Запустите echo $DOCKER_HOST
, чтобы увидеть IP-адрес и настроить порт на порт 3000.
Комментарии:
1. Я попробовал это, и я получаю curl: (56) Сбой Recv: сброс соединения одноранговым узлом
2. Когда я запускаю «echo $ DOCKER_HOST», я ничего не получаю. Означает ли это, что я что-то настроил неправильно?
3. @LukeKelly нет, это означает, что вы используете последнюю (за последние несколько лет) версию docker.
4. @LukeKelly контейнер все еще запущен? Включите
docker container ls -a
в свой вопрос. Также укажите,docker container logs $id
где$id
находится ваш идентификатор контейнера.5. Спасибо за вашу помощь! Я добавил запрошенную информацию выше.
Ответ №3:
После дополнительных поисковых запросов я последовал этому руководству и создал свою собственную «определяемую пользователем мостовую сеть».
Если я запускаю свой контейнер и подключаю его к этой сети, тогда он работает! Я был бы рад, если бы кто-нибудь мог объяснить, почему!
Комментарии:
1. Похоже, что вы запускаете curl из другого контейнера, а не с хоста на опубликованный порт. Сетевые правила сильно отличаются для этого сценария.