Сколько раз вы открывали терминал и забывали простую Docker команду? Гугл в помощь, потом опять ищете то же самое через неделю. Рассказываем про команды, которые нужны в реальной работе.
Вам нужно видеть, какие контейнеры работают прямо сейчас:
docker ps
Это покажет только живые контейнеры. Но если контейнер упал или его остановили, он исчезнет из списка.
Чтобы увидеть всё, включая мёртвые:
docker ps -a
Самая частая команда в разработке:
docker run -d -p 8080:80 nginx
Разбираем:
-d — запустить в фоне, чтобы терминал не занимался.-p 8080:80 — проксировать локальный порт 8080 на порт 80 внутри контейнера.nginx — образ, который запускаем.Результат: контейнер крутится в фоне, вы можете открыть http://localhost:8080 и увидите nginx.
Контейнер поднялся, поэкспериментировали, теперь нужно его убить:
docker stop имя-или-id
Контейнер остановится, но останется на диске.
Если нужно удалить совсем:
docker rm имя-или-id
Или в один ход — остановить и удалить:
docker rm -f имя-или-id
Флаг
-f форсирует удаление даже если контейнер работает.Посмотреть все образы у вас на машине:
docker images
Удалить образ, если он вам больше не нужен:
docker rmi название-образа
Если удалите образ, контейнеры которые на нём основаны, перестанут работать.
Контейнер падает или работает странно? Посмотрите логи:
docker logs имя-или-id
Это покажет всё что контейнер вывел в stdout.
Можно добавить флаг -f чтобы следить в реальном времени:
docker logs -f имя-или-id
Иногда нужно залезть внутрь контейнера и что-то проверить. Откройте интерактивный шелл:
docker exec -it имя-или-id bash
Флаг
-it означает интерактивный терминал. Теперь вы внутри, можете запускать команды, смотреть файлы, отлаживать.Ещё полезно посмотреть детали контейнера:
docker inspect имя-или-id
Будет JSON со всей информацией: какие переменные окружения, какие портами, версии образа, сетевая конфигурация.
Со временем контейнеры и образы накапливаются. Чистим:
docker system prune -a
Это удалит все остановленные контейнеры, все неиспользуемые образы, сети и volumes которые ни на что не ссылаются.
Контейнер падает, данные теряются — такое быть не должно. Для этого есть тома:
docker volume create my_volume
Теперь у вас есть том. Запускаете контейнер и монтируете том внутрь:
docker run -d -v my_volume:/data nginx
Флаг
-v монтирует том my_volume в папку /data внутри контейнера. Когда контейнер упадёт, данные в томе остаются. Запустите контейнер снова — данные на месте.По умолчанию контейнеры могут общаться через IP адреса, но это хрупко. Правильнее создать свою сеть:
docker network create my_network
Теперь запускаете контейнеры в этой сети:
docker run -d --network my_network --name api nginx
docker run -d --network my_network --name db postgres
Контейнеры внутри сети видят друг друга по имени. Это удобнее чем помнить IP адреса.
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29🔥3🥱1
🛠 Как найти и починить утечки, которые валят API
API падает каждый день? Память растёт, горутины множатся, потом крах. Это не магия — это утечки ресурсов. Вот как их найти и убить.
Шаг 1: Собрать доказательства перед тем как гадать
Не начинайте с предположений. Сначала соберите логи. Ищите паттерны: растут ли таймауты, появляются ошибки «context canceled», скачет ли error rate?
Heap и goroutine профили. Это главное. Добавьте pprof endpoint, если его нет:
На следующем инциденте вытащите профили:
Проверьте лимиты: /proc/<pid>/limits, количество открытых файловых дескрипторов, состояние сокетов.
Шаг 2: Прочитать профили и понять, что протекает
Откройте goroutine профиль текстом — там все ответы:
Что нужно найти:
• Горутины в CLOSE_WAIT. Это сокеты, которые никто не закрыл нормально.
• Горутины, зависшие на channel send/receive. Если тысячи горутин ждут отправить или получить из канала — канал где-то забился или заблокирован.
• Горутины в syscall. Много горутин ждут на сетевых операциях — это может быть утечка соединений или зависание на стороне сервера.
Шаг 3: Найти корни утечек в коде
Три главных виновника:
• Горутины без контекста. Запустили горутину для async операции, но не гарантировали её завершение:
• HTTP клиенты без переиспользования. Создаёте нового клиента на каждый запрос:
• Неограниченные очереди. На пике нагрузки канал растёт без предела:
Чтобы не падать в проде можно попробовать имитировать нагрузку на дев стенде:
Растёт ли количество горутин? Если да — утечка. Если нет — ложная тревога.
Не полагайтесь только на профили. Мониторьте в реальном времени:
Выставляйте эти метрики в Prometheus или что у вас есть. Алерты на рост горутин выше нормы — это первый звоночек.
Не решайте задачу вслепую. Профилируйте, смотрите данные, ищите паттерны. Утечки это не магия — это просто ресурсы, которые вы забыли закрыть.
🐸 Библиотека Go-разработчика
#GoToProduction
API падает каждый день? Память растёт, горутины множатся, потом крах. Это не магия — это утечки ресурсов. Вот как их найти и убить.
Шаг 1: Собрать доказательства перед тем как гадать
Не начинайте с предположений. Сначала соберите логи. Ищите паттерны: растут ли таймауты, появляются ошибки «context canceled», скачет ли error rate?
Heap и goroutine профили. Это главное. Добавьте pprof endpoint, если его нет:
import _ "net/http/pprof"
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
На следующем инциденте вытащите профили:
curl localhost:6060/debug/pprof/heap > heap.pb
curl localhost:6060/debug/pprof/goroutine?debug=2 > goroutines.txt
Проверьте лимиты: /proc/<pid>/limits, количество открытых файловых дескрипторов, состояние сокетов.
Шаг 2: Прочитать профили и понять, что протекает
Откройте goroutine профиль текстом — там все ответы:
go tool pprof -http=:8080 heap.pb
Что нужно найти:
• Горутины в CLOSE_WAIT. Это сокеты, которые никто не закрыл нормально.
• Горутины, зависшие на channel send/receive. Если тысячи горутин ждут отправить или получить из канала — канал где-то забился или заблокирован.
• Горутины в syscall. Много горутин ждут на сетевых операциях — это может быть утечка соединений или зависание на стороне сервера.
Шаг 3: Найти корни утечек в коде
Три главных виновника:
• Горутины без контекста. Запустили горутину для async операции, но не гарантировали её завершение:
// Плохо: горутина может зависнуть
go func() {
resp, _ := http.Get(url)
// ...
}()
// Хорошо: контекст отменяет работу
go func(ctx context.Context) {
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, _ := httpClient.Do(req)
}(r.Context())
• HTTP клиенты без переиспользования. Создаёте нового клиента на каждый запрос:
// Плохо: новый Transport на каждый вызов
func handleRequest(w http.ResponseWriter, r *http.Request) {
client := &http.Client{}
resp, _ := client.Get("https://api.example.com/data")
}
// Хорошо: переиспользуем один клиент
var httpClient = &http.Client{
Transport: &http.Transport{
MaxIdleConns: 200,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: 90 * time.Second,
},
}
• Неограниченные очереди. На пике нагрузки канал растёт без предела:
// Плохо: неограниченный канал
jobs := make(chan Job)
// Хорошо: ограничиваем размер
jobs := make(chan Job, 1000)
select {
case jobs <- job:
// принято
default:
http.Error(w, "перегружены", http.StatusServiceUnavailable)
}
Чтобы не падать в проде можно попробовать имитировать нагрузку на дев стенде:
# Генерируем нагрузку
ab -n 100000 -c 100 http://localhost:8080/endpoint
# В другом терминале снимаем профиль каждую минуту
for i in {1..60}; do
curl localhost:6060/debug/pprof/goroutine?debug=1 > goroutine_$i.txt
sleep 60
done
Растёт ли количество горутин? Если да — утечка. Если нет — ложная тревога.
Не полагайтесь только на профили. Мониторьте в реальном времени:
// Метрика: количество горутин
runtime.NumGoroutine()
// Метрика: память
var m runtime.MemStats
runtime.ReadMemStats(&m)
m.Alloc // текущее использование
// Метрика: открытые файловые дескрипторы (Linux)
files, _ := ioutil.ReadDir("/proc/self/fd")
len(files) // количество открытых fd
Выставляйте эти метрики в Prometheus или что у вас есть. Алерты на рост горутин выше нормы — это первый звоночек.
Не решайте задачу вслепую. Профилируйте, смотрите данные, ищите паттерны. Утечки это не магия — это просто ресурсы, которые вы забыли закрыть.
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26🔥7❤4😢1
Задача проста на вид, но открывает много вопросов на интервью. Вот почему её так любят спрашивать.
Дано число n. Нужно вернуть массив строк, где для каждого числа от 1 до n:
• если кратно и 3 и 5 — «FizzBuzz»
• если кратно 3 — «Fizz»
• если кратно 5 — «Buzz»
• иначе — само число как строку
Решение:
func fizzBuzz(n int) []string {
res := make([]string, n)
for i := 1; i <= n; i++ {
res[i-1] = strconv.Itoa(i)
if i % 3 == 0 { res[i-1] = "Fizz" }
if i % 5 == 0 { res[i-1] = "Buzz" }
if i % 15 == 0 { res[i-1] = "FizzBuzz" }
}
return res
}Число 15 — это наименьшее общее кратное чисел 3 и 5. Когда число одновременно делится на 3 и на 5, оно всегда делится на 15.
На собеседовании сначала напишите просто, потом обсудите улучшения. FizzBuzz — не про трюки синтаксиса, а про чистоту мышления и умение общаться с интервьюером.
#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱9👍6😁3🤔1
🧑💻 Среда или понедельник
Как у вас началась рабочая трёхдневка? У админа сбились абсолютно все настройки по пониманию какой сейчас день недели. Тяжелее только новогодние праздники.
💬 Работаете или взяли хитрый отпуск? Ждём вас в комментах 👇
🐸 Библиотека Go-разработчика
#GoTalk
Как у вас началась рабочая трёхдневка? У админа сбились абсолютно все настройки по пониманию какой сейчас день недели. Тяжелее только новогодние праздники.
#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
😁9🥱1
Forwarded from Библиотека IT-мемов
This media is not supported in your browser
VIEW IN TELEGRAM
😁43🤔2
GoCrypt изначально просто проходил через все поля структуры на каждый вызов, искал теги, выполнял рефлексию. Для больших структур это замедлялось быстро.
Новая версия 1.1.0 это переработала.
Раньше каждый вызов
Encrypt() и Decrypt() переанализировал структуру с нуля. Если вы обрабатываете пользователя с 15 полями, где только 3–4 нужно шифровать, библиотека изучала все 15. В тысячный раз.Теперь типы кешируются через
sync.Map. Первый проход — сохраняются информация о том, какие поля нужны. Все последующие операции просто смотрят в кеш. #GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤1😁1
SQL-инъекция — это не призрак из учебников по безопасности. Это реальная уязвимость, которая прячется в коде, написанном в спешке. И она может находиться в вашем приложении прямо сейчас.Её главная фишка в том, что она выглядит безобидно.
Пара строк кода, которые кажутся логичными и работают в тестах. Но в боевых условиях это становится открытой дверью в вашу базу данных.
Когда вы склеиваете SQL-запрос из частей, вы решаете за базу данных, что считать кодом, а что — данными. И вы почти гарантированно ошибаетесь.
Хакер, в отличие от вас, знает это. Он понимает, что можно передать в поле username и заставить его работать как код. Он не пытается угадать пароль — он меняет саму структуру запроса.
Параметризованные запросы — это не украшение, а архитектура
Разница между уязвимым и безопасным кодом — это не регулярные выражения или специальные функции для очистки. Это просто разделение: запрос идёт одним пакетом, данные — другим.
// Сначала структура...
query := "SELECT id, username, email FROM users WHERE username = ?"
// ...потом данные
err := db.QueryRow(query, username).Scan(&id, &uname, &email)
Драйвер БД уже знает, что делать. Он не будет интерпретировать данные как команды.
Одной инъекции недостаточно, чтобы взломать приложение, если на входе стоит валидация.
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21❤2
Новичок пишет код примерно так:
res, err := http.Get(url)
Выглядит невинно, но если вызов зависнет, то зависнет и горутина. Навсегда. Нет таймаута, нет способа его отменить. Сервис просто накапливает горутины, пока не упадёт.
Профессионалы всегда передают контекст через все слои приложения:
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
res, err := http.DefaultClient.Do(req)
Они распространяют его на весь путь — от HTTP хендлера через бизнес-логику до репозиториев:
func (r *UserRepo) Get(ctx context.Context, id int) (*User, error) {
// ctx здесь и управляет отменой, и ловит таймауты
}Это не просто хорошая практика — это основа надёжности.
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍28🤔5❤1💯1
gologin предоставляет цепочки http.Handler-ов для аутентификации через Google, GitHub, Twitter, Bitbucket, Tumblr или любых других OAuth1 и OAuth2 провайдеров.
Вместо того, чтобы вручную парсить OAuth-потоки, обрабатывать CSRF-токены и делать API-запросы за данными пользователя, вы просто подключаете готовые обработчики и получаете аутентифицированного пользователя в контексте запроса.
Быстрый старт
Интегрировать вход через GitHub занимает всего несколько строк:
import (
"github.com/dghubble/gologin/v2"
"github.com/dghubble/gologin/v2/github"
"golang.org/x/oauth2"
githubOAuth2 "golang.org/x/oauth2/github"
)
config := &oauth2.Config{
ClientID: "YourGithubClientID",
ClientSecret: "YourGithubClientSecret",
RedirectURL: "http://localhost:8080/callback",
Endpoint: githubOAuth2.Endpoint,
}
mux := http.NewServeMux()
mux.Handle("/login",
github.StateHandler(gologin.DefaultCookieConfig,
github.LoginHandler(config, nil)))
mux.Handle("/callback",
github.StateHandler(gologin.DefaultCookieConfig,
github.CallbackHandler(config, issueSession(), nil)))
Готово. Пользователь нажимает на
/login, перенаправляется на GitHub, а затем на /callback с кодом авторизации.Для веб-приложений используются LoginHandler и CallbackHandler, которые управляют редиректами.
Для мобильных приложений есть TokenHandler, который работает с токенами, передаваемыми напрямую. Twitter, например, включает специальный TokenHandler именно для таких случаев.
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤5⚡1
🎁 И мозг прокачать, и макбук утащить!
Proglib.academy разыгрывает MacBook Pro 14 (M3 Pro, 36 GB, 1 TB SSD) 💻
Условия:
1️⃣ Покупаешь любой курс Proglib до 15 ноября.
2️⃣ Проходишь минимум 2 учебные недели (можно осилить за два вечера).
3️⃣ Пишешь куратору в чат своего курса: #розыгрыш.
Что за курсы?
— Математика для Data Science (6 месяцев боли и просветления).
— Основы Python, ML, алгоритмы, AI-агенты и даже курс для тех, кто в IT, но не кодит.
👉 Участвовать в розыгрыше
Proglib.academy разыгрывает MacBook Pro 14 (M3 Pro, 36 GB, 1 TB SSD) 💻
Условия:
1️⃣ Покупаешь любой курс Proglib до 15 ноября.
2️⃣ Проходишь минимум 2 учебные недели (можно осилить за два вечера).
3️⃣ Пишешь куратору в чат своего курса: #розыгрыш.
Что за курсы?
— Математика для Data Science (6 месяцев боли и просветления).
— Основы Python, ML, алгоритмы, AI-агенты и даже курс для тех, кто в IT, но не кодит.
👉 Участвовать в розыгрыше
🥱3❤2🤔1🤩1
💻 От логирования к передаче вверх
Go известен своей простотой, но именно в этой простоте скрыта мощная возможность — передача ошибок вверх по стеку вызовов. Часто начинающие разработчики просто логируют ошибку и возвращают nil, теряя всю информацию о контексте:
Такое решение убивает возможность понять, где именно и почему произошла ошибка.
Вот как это делают опытные разработчики:
🐸 Библиотека Go-разработчика
#GoToProduction
Go известен своей простотой, но именно в этой простоте скрыта мощная возможность — передача ошибок вверх по стеку вызовов. Часто начинающие разработчики просто логируют ошибку и возвращают nil, теряя всю информацию о контексте:
user, err := repo.GetUser(id)
if err != nil {
log.Println("failed to get user:", err)
return nil
}
Такое решение убивает возможность понять, где именно и почему произошла ошибка.
Вот как это делают опытные разработчики:
user, err := repo.GetUser(ctx, id)
if err != nil {
return nil, fmt.Errorf("get user %d: %w", id, err)
}
%w — это ключ к вложенным ошибкам в Go 1.13 и новее. Такой подход сохраняет смысл ошибки и ее цепочку, что помогает в отладке и трассировке.#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25🥱6❤3
📰 Дайджест недели
Вот и прошла трёхдневная рабочая неделя. Вспоминаем что произошло.
— Ещё один ИИ из Китая
— Свежий Cup o' Go
— У Firefox новый маскот
— Как найти и починить утечки, которые валят API
— GoCrypt 1.1.0
🐸 Библиотека Go-разработчика
#GoLive
Вот и прошла трёхдневная рабочая неделя. Вспоминаем что произошло.
— Ещё один ИИ из Китая
— Свежий Cup o' Go
— У Firefox новый маскот
— Как найти и починить утечки, которые валят API
— GoCrypt 1.1.0
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Anonymous Poll
27%
Мемы
15%
Список сокращений
28%
Про кастомные ошибки
25%
Команды для работы с докером
36%
Поиск и устранение утечек
34%
Либа для OAuth
39%
Про небезопасные обращения к БД
36%
Про обработку ошибок
👍3
💻 ВАЖНО: макбук ещё не забрали!
Proglib.academy продолжает розыгрыш MacBook Pro 14» (M3 Pro, 36 Гб, 1 Тб SSD).
Что нужно для участия?
— Берёшь любой курс Академии до 15 ноября.
— Проходишь хотя бы 2 недели обучения (можно за два дня ).
— Пишешь куратору #розыгрыш. Всё — ты в игре!
Что за курсы?
▫️Алгоритмы и структуры данных — если хочешь готовиться к собесам в Яндекс, FAANG и не сидеть на джуне вечно.
▫️Архитектуры и шаблоны проектирования — учат думать как senior, а не просто писать код.
▫️ Python, математика для DS, основы IT и другие темы — можно стартовать с нуля или усилить то, что уже знаешь.
👉 Влетай, не думай!
Proglib.academy продолжает розыгрыш MacBook Pro 14» (M3 Pro, 36 Гб, 1 Тб SSD).
Что нужно для участия?
— Берёшь любой курс Академии до 15 ноября.
— Проходишь хотя бы 2 недели обучения (
— Пишешь куратору #розыгрыш. Всё — ты в игре!
Что за курсы?
▫️Алгоритмы и структуры данных — если хочешь готовиться к собесам в Яндекс, FAANG и не сидеть на джуне вечно.
▫️Архитектуры и шаблоны проектирования — учат думать как senior, а не просто писать код.
▫️ Python, математика для DS, основы IT и другие темы — можно стартовать с нуля или усилить то, что уже знаешь.
👉 Влетай, не думай!
🥱9😁2👍1👾1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁39❤5🥱2
Многие начинающие Go-разработчики организуют проекты, разделяя файлы по типам — например, отдельные папки для моделей, обработчиков, утилит. Такая схема выглядит аккуратно:
/models
/utils
/handlers
Однако за этим скрываются проблемы: тесная связанность кода и круговые зависимости между пакетами.
Современный подход — разделять код по доменам и ответственности. Например, структура может выглядеть так:
/internal
/user
handler.go
service.go
repository.go
/pkg
/config
/logger
/cmd
/api
main.go
Это стандарт для крупных систем, таких как Uber или Cloudflare. Даже команда Go рекомендует именно такой подход.
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
❤30👍8🌚5⚡2😢2
💻 Хочешь MacBook Pro? Просто начни учиться!
Да-да, вы не ослышались: Proglib.academy дарит макбук за учёбу!
Всё просто:
— купи любой курс Академии до 15 ноября;
— пройди 2 недели обучения (можно за два дня);
— напиши куратору в чате курса хэштег #розыгрыш.
📚 Выбирай свой курс:
▫️ «Математика для DS» — для тех, кто хочет уверенно работать с данными;
▫️ «Основы Python» — чтобы начать писать код с нуля;
▫️ «Алгоритмы и структуры данных» — для будущих инженеров;
▫️ «AI-агенты» или «Машинное обучение» — для тех, кто хочет прокачаться в ИИ.
👉 Участвовать в розыгрыше
Да-да, вы не ослышались: Proglib.academy дарит макбук за учёбу!
Всё просто:
— купи любой курс Академии до 15 ноября;
— пройди 2 недели обучения (можно за два дня);
— напиши куратору в чате курса хэштег #розыгрыш.
📚 Выбирай свой курс:
▫️ «Математика для DS» — для тех, кто хочет уверенно работать с данными;
▫️ «Основы Python» — чтобы начать писать код с нуля;
▫️ «Алгоритмы и структуры данных» — для будущих инженеров;
▫️ «AI-агенты» или «Машинное обучение» — для тех, кто хочет прокачаться в ИИ.
👉 Участвовать в розыгрыше
👍1😁1
Go Developer — от 3 000 до 7 000 $
Middle GO разработчик на удалёнку
Джун Go разработчик — от 1 700 $
Golang-разработчик — от 200 000 ₽
#GoWork
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2
Дано n монет. Нужно выложить лестницу, где на i-й ступени ровно i монет. Вернуть количество полных рядов лестницы, которые удастся построить.
Наивный перебор даёт O(n), но попробуем быстрее:
func arrangeCoins(n int) int {
left, right := 0, n
for left <= right {
mid := left + (right-left)/2
sum := mid * (mid + 1) / 2
if sum == n {
return mid
}
if sum < n {
left = mid + 1
} else {
right = mid - 1
}
}
return right
}Вместо перебора каждого уровня, бинарный поиск за O(log n) найдёт точный ответ.
#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤1
🛒 Black Friday от Proglib.academy!
Только до 30 ноября — скидка 40% на ВСЕ курсы.
Пора добавить в корзину не носки, а новые скиллы: Python, математика для Data Science, AI, алгоритмы и структуры данных, ML.
🎓 Выбирай курс, который реально двинет тебя в карьере, и учись со скидкой.
👉 Учиться со скидкой
Только до 30 ноября — скидка 40% на ВСЕ курсы.
Пора добавить в корзину не носки, а новые скиллы: Python, математика для Data Science, AI, алгоритмы и структуры данных, ML.
🎓 Выбирай курс, который реально двинет тебя в карьере, и учись со скидкой.
👉 Учиться со скидкой
👍1