Bagaimana cara menyesuaikan file konfigurasi gambar Docker PostgreSQL resmi?

102

Saya menggunakan image Postgres Docker resmi mencoba menyesuaikan konfigurasinya. Untuk tujuan ini, saya menggunakan perintah seduntuk mengubah max_connectionsmisalnya:

sed -i -e"s/^max_connections = 100.*$/max_connections = 1000/" /var/lib/postgresql/data/postgresql.conf

Saya mencoba dua metode untuk menerapkan konfigurasi ini. Yang pertama adalah dengan menambahkan perintah ke skrip dan menyalinnya di dalam folder init "/docker-entrypoint-initdb.d". Metode kedua adalah dengan menjalankannya langsung di dalam Dockerfile saya dengan perintah "RUN" (metode ini bekerja dengan baik dengan gambar Postgresql tidak resmi dengan jalur berbeda ke file konfigurasi "/ etc / postgres / ..."). Dalam kedua kasus, perubahan gagal karena file konfigurasi hilang (saya pikir itu belum dibuat).

Bagaimana cara mengubah konfigurasi?

Edit 1:

Berikut adalah Dockerfile yang digunakan untuk membuat image:

# Database (http://www.cs3c.ma/)

FROM postgres:9.4
MAINTAINER Sabbane <contact@cs3c.ma>

ENV TERM=xterm

RUN apt-get update
RUN apt-get install -y nano

ADD scripts /scripts
# ADD scripts/setup-my-schema.sh /docker-entrypoint-initdb.d/

# Allow connections from anywhere.
RUN sed -i -e"s/^#listen_addresses =.*$/listen_addresses = '*'/" /var/lib/postgresql/data/postgresql.conf
RUN echo "host    all    all    0.0.0.0/0    md5" >> /var/lib/postgresql/data/pg_hba.conf

# Configure logs
RUN sed -i -e"s/^#logging_collector = off.*$/logging_collector = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_directory = 'pg_log'.*$/log_directory = '\/var\/log\/postgresql'/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_filename = 'postgresql-\%Y-\%m-\%d_\%H\%M\%S.log'.*$/log_filename = 'postgresql_\%a.log'/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_file_mode = 0600.*$/log_file_mode = 0644/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_truncate_on_rotation = off.*$/log_truncate_on_rotation = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_rotation_age = 1d.*$/log_rotation_age = 1d/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_min_duration_statement = -1.*$/log_min_duration_statement = 0/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_checkpoints = off.*$/log_checkpoints = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_connections = off.*$/log_connections = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_disconnections = off.*$/log_disconnections = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^log_line_prefix = '\%t \[\%p-\%l\] \%q\%u@\%d '.*$/log_line_prefix = '\%t \[\%p\]: \[\%l-1\] user=\%u,db=\%d'/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_lock_waits = off.*$/log_lock_waits = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_temp_files = -1.*$/log_temp_files = 0/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#statement_timeout = 0.*$/statement_timeout = 1800000        # in milliseconds, 0 is disabled (current 30min)/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^lc_messages = 'en_US.UTF-8'.*$/lc_messages = 'C'/" /var/lib/postgresql/data/postgresql.conf

# Performance Tuning
RUN sed -i -e"s/^max_connections = 100.*$/max_connections = 1000/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^shared_buffers =.*$/shared_buffers = 16GB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#effective_cache_size = 128MB.*$/effective_cache_size = 48GB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#work_mem = 1MB.*$/work_mem = 16MB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#maintenance_work_mem = 16MB.*$/maintenance_work_mem = 2GB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#checkpoint_segments = .*$/checkpoint_segments = 32/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#checkpoint_completion_target = 0.5.*$/checkpoint_completion_target = 0.7/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#wal_buffers =.*$/wal_buffers = 16MB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#default_statistics_target = 100.*$/default_statistics_target = 100/" /var/lib/postgresql/data/postgresql.conf


VOLUME ["/var/lib/postgresql/data", "/var/log/postgresql"]

CMD ["postgres"]

Dengan Dockerfile ini, proses build menunjukkan kesalahan: sed: can't read /var/lib/postgresql/data/postgresql.conf: No such file or directory

Sakr
sumber
1
salah satu caranya adalah dengan menggunakan gambar resmi, mulai, hubungkan di dalam docker exec -it container_id bashkemudian lakukan modifikasi Anda, lalu docker commit container_id myuser/myimage_myPostegresql:myversionlihat dokumen docs.docker.com/reference/commandline/cli/#commit
user2915097
2
Saya rasa salah satu keuntungan dari paradigma buruh pelabuhan adalah mengotomatiskan seluruh proses pembuatan. Seperti yang disebutkan dengan image lain, paintedfox/postgresqldimungkinkan untuk mengubah konfigurasi secara langsung di dalam Dockerfile. Saya pikir itu juga bisa dilakukan dengan gambar resmi.
Sakr
metode sed harus bekerja, dapatkah Anda memposting Dcokerfile Anda atau reproduksi lengkap?
pengguna2915097

Jawaban:

54

Itu postgres:9.4 gambar yang telah mewarisi dari menyatakan volume di/var/lib/postgresql/data . Ini pada dasarnya berarti Anda tidak dapat menyalin file apa pun ke jalur itu di gambar Anda; perubahan akan dibuang.

Anda punya beberapa pilihan:

  • Anda bisa menambahkan file konfigurasi Anda sendiri sebagai volume pada saat run-time dengan docker run -v postgresql.conf:/var/lib/postgresql/data/postgresql.conf ... . Namun, saya tidak yakin persis bagaimana itu akan berinteraksi dengan volume yang ada.

  • Anda dapat menyalin file saat penampung dimulai. Untuk melakukan itu, salin file Anda ke dalam build di lokasi yang tidak di bawah volume lalu panggil skrip dari entrypoint atau cmd yang akan menyalin file ke lokasi yang benar dan memulai postgres.

  • Kloning proyek di belakang gambar resmi Postgres dan edit Dockerfile untuk menambahkan file konfigurasi Anda sendiri sebelum VOLUME dideklarasikan (apa pun yang ditambahkan sebelum instruksi VOLUME secara otomatis disalin pada saat run-time).

  • Lewati semua perubahan konfigurasi dalam opsi perintah di file tulis-galangan

Suka:

services:
  postgres:
    ...  
    command:
      - "postgres"
      - "-c"
      - "max_connections=1000"
      - "-c"
      - "shared_buffers=3GB"
      - "-c"
      ...
Adrian Mouat
sumber
3
Itu saja, perubahan seharusnya tidak ada di dalam Dockerfile. Saya telah memindahkannya ke skrip dan memanggilnya dari entrypoint dan berfungsi dengan baik sekarang. Terima kasih atas jawabannya.
Sakr
5
Saya baru saja menyalin skrip di dalam folder init "/docker-entrypoint-initdb.d/" dan kali ini juga berfungsi dengan baik. Itu aneh tapi sepertinya saya begitu fokus pada pengaturan gambar dengan Dockerfile, seperti yang biasa saya lakukan dengan kebanyakan gambar, sehingga saya melewatkan sesuatu dengan percobaan pertama saya menggunakan skrip init.
Sakr
"Ini pada dasarnya berarti Anda tidak dapat menyalin file apa pun ke jalur itu pada gambar Anda; perubahan akan dibuang." Bisakah Anda menjelaskan mengapa demikian?
isco
@isco mencari volume di dokumen resmi. Pada dasarnya volume tidak disimpan dalam gambar tetapi di host, jadi data akan disimpan di host, bukan di gambar. Anda harus memulai penampung dengan volume yang sama terpasang untuk menyimpan data.
Adrian Mouat
saya mengubah /var/lib/postgres/data/pg_hba.conf untuk menerima koneksi saja adalah host semua 192.168.0.0/0 md5 dan host komentar semua semua md5 (default). Tapi jangan ubah efeknya
Lucas Resende
83

Dengan Docker Compose

Ketika bekerja dengan Docker Compose, Anda dapat menggunakan command: postgres -c option=valuedi Anda docker-compose.ymluntuk mengkonfigurasi Postgres.

Misalnya, ini membuat Postgres masuk ke file:

command: postgres -c logging_collector=on -c log_destination=stderr -c log_directory=/logs

Mengadaptasi jawaban Vojtech Vitek , Anda dapat menggunakan

command: postgres -c config_file=/etc/postgresql.conf

untuk mengubah file konfigurasi yang akan digunakan Postgres. Anda akan memasang file konfigurasi khusus Anda dengan volume:

volumes:
   - ./customPostgresql.conf:/etc/postgresql.conf

Inilah docker-compose.ymlaplikasi saya, menunjukkan cara mengkonfigurasi Postgres:

# Start the app using docker-compose pull && docker-compose up to make sure you have the latest image
version: '2.1'
services:
  myApp:
    image: registry.gitlab.com/bullbytes/myApp:latest
    networks:
      - myApp-network
  db:
     image: postgres:9.6.1
     # Make Postgres log to a file.
     # More on logging with Postgres: https://www.postgresql.org/docs/current/static/runtime-config-logging.html
     command: postgres -c logging_collector=on -c log_destination=stderr -c log_directory=/logs
     environment:
       # Provide the password via an environment variable. If the variable is unset or empty, use a default password
       - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-4WXUms893U6j4GE&Hvk3S*hqcqebFgo!vZi}
     # If on a non-Linux OS, make sure you share the drive used here. Go to Docker's settings -> Shared Drives
     volumes:
       # Persist the data between container invocations
       - postgresVolume:/var/lib/postgresql/data
       - ./logs:/logs
     networks:
       myApp-network:
         # Our application can communicate with the database using this hostname
         aliases:
           - postgresForMyApp
networks:
  myApp-network:
    driver: bridge
# Creates a named volume to persist our data. When on a non-Linux OS, the volume's data will be in the Docker VM
# (e.g., MobyLinuxVM) in /var/lib/docker/volumes/
volumes:
  postgresVolume:

Izin untuk menulis ke direktori log

Perhatikan bahwa saat di Linux, direktori log di host harus memiliki izin yang tepat. Jika tidak, Anda akan mendapatkan kesalahan yang sedikit menyesatkan

FATAL: tidak dapat membuka file log "/logs/postgresql-2017-02-04_115222.log": Izin ditolak

Saya katakan menyesatkan, karena pesan kesalahan menunjukkan bahwa direktori dalam wadah memiliki izin yang salah, padahal pada kenyataannya direktori pada host tidak mengizinkan penulisan.

Untuk memperbaikinya, saya menetapkan izin yang benar pada host menggunakan

chgroup ./logs docker && chmod 770 ./logs
Matthias Braun
sumber
Apakah Anda merekomendasikan membuat log postgres ke file, daripada stdout dan menggunakan perintah log docker untuk menghadapinya? pujian untuk penautan silang dalam masalah github !
jpic
1
Saya tidak memutuskan apakah masuk ke file atau menggunakan log Docker lebih disukai, jpic.
Matthias Braun
Anda menambahkan kata sandi, yang mungkin ingin Anda
tutupi di
3
@vidstige: Saya tidak menggunakan string acak ini sebagai kata sandi, ini hanya untuk demonstrasi.
Matthias Braun
1
@ Gherman: Apakah Anda menambahkan ini ke Dockerfile Anda? Karena seharusnya tidak. Jawaban saya menggunakan docker-compose.yml.
Matthias Braun
39

Masukkan postgresql.conf kustom ke dalam container Docker postgres

File default postgresql.confberada di dalam PGDATAdir ( /var/lib/postgresql/data), yang membuat segalanya menjadi lebih rumit terutama saat menjalankan container postgres untuk pertama kalinya, karena docker-entrypoint.shpembungkus memanggil initdblangkah untukPGDATA inisialisasi dir.

Untuk menyesuaikan konfigurasi PostgreSQL di Docker secara konsisten, saya sarankan untuk menggunakan config_file opsi postgres bersama dengan volume Docker seperti ini:

Basis data produksi (dir PGDATA sebagai Volume Persisten)

docker run -d \
-v $CUSTOM_CONFIG:/etc/postgresql.conf \
-v $CUSTOM_DATADIR:/var/lib/postgresql/data \
-e POSTGRES_USER=postgres \
-p 5432:5432 \
--name postgres \
postgres:9.6 postgres -c config_file=/etc/postgresql.conf

Database pengujian (dir PGDATA akan dibuang setelah docker rm)

docker run -d \
-v $CUSTOM_CONFIG:/etc/postgresql.conf \
-e POSTGRES_USER=postgres \
--name postgres \
postgres:9.6 postgres -c config_file=/etc/postgresql.conf

Debugging

  1. Hapus -d(opsi lepas) dari docker runperintah untuk melihat log server secara langsung.
  2. Hubungkan ke server postgres dengan klien psql dan buat kueri konfigurasi:

    docker run -it --rm --link postgres:postgres postgres:9.6 sh -c 'exec psql -h $POSTGRES_PORT_5432_TCP_ADDR -p $POSTGRES_PORT_5432_TCP_PORT -U postgres'
    
    psql (9.6.0)
    Type "help" for help.
    
    postgres=# SHOW all;
Vojtech Vitek
sumber
30

Saat Anda menjalankan entrypoint resmi (AKA saat Anda meluncurkan penampung), itu berjalan initdbdi $PGDATA( /var/lib/postgresql/datasecara default), dan kemudian menyimpan di direktori itu 2 file ini:

  • postgresql.conf dengan pengaturan manual default.
  • postgresql.auto.confdengan pengaturan diganti secara otomatis dengan ALTER SYSTEMperintah.

Titik masuk juga menjalankan /docker-entrypoint-initdb.d/*.{sh,sql}file apa pun .

Semua ini berarti Anda dapat menyediakan skrip shell / SQL di folder itu yang mengkonfigurasi server untuk boot berikutnya (yang akan segera setelah inisialisasi DB, atau saat berikutnya Anda mem-boot container).

Contoh:

conf.sql mengajukan:

ALTER SYSTEM SET max_connections = 6;
ALTER SYSTEM RESET shared_buffers;

Dockerfile mengajukan:

FROM posgres:9.6-alpine
COPY *.sql /docker-entrypoint-initdb.d/
RUN chmod a+r /docker-entrypoint-initdb.d/*

Dan kemudian Anda harus mengeksekusi conf.sqlsecara manual di database yang sudah ada. Karena konfigurasi disimpan dalam volume, itu akan bertahan dari pembangunan kembali.


Alternatif lain adalah mengoper -cbendera sebanyak yang Anda inginkan:

docker container run -d postgres -c max_connections=6 -c log_lock_waits=on

Dengan cara ini Anda tidak perlu membangun image baru, dan Anda tidak perlu peduli dengan database yang sudah ada atau tidak; semua akan terpengaruh.

Yajo
sumber
2
Yang terakhir ini, lewat -c, adalah favorit saya. Ini sangat bersih & mudah dibuat untuk lingkungan yang berbeda.
epic_fil
10

Anda dapat menempatkan kustom Anda postgresql.confdi file sementara di dalam penampung, dan menimpa konfigurasi default saat runtime.

Untuk melakukannya :

  • Salin kebiasaan postgresql.confAnda di dalam penampung Anda
  • Salin updateConfig.shfile tersebut/docker-entrypoint-initdb.d/

Dockerfile

FROM postgres:9.6

COPY postgresql.conf      /tmp/postgresql.conf
COPY updateConfig.sh      /docker-entrypoint-initdb.d/_updateConfig.sh

updateConfig.sh

#!/usr/bin/env bash

cat /tmp/postgresql.conf > /var/lib/postgresql/data/postgresql.conf

Saat runtime, penampung akan mengeksekusi skrip di dalamnya /docker-entrypoint-initdb.d/dan menimpa konfigurasi default dengan konfigurasi kustom Anda.

alphayax.dll
sumber
mengapa "_" di perintah salin kedua? shouldnt itu: /docker-entrypoint-initdb.d/updateConfig.sh?
Fernando Castilla Ospina
3
Itu karena folder docker-entrypoint-initdb.d / menjalankan skrip dalam urutan abjad. Dan saya ingin menerapkan skrip ini sebelum yang lain.
alphayax
tnx saya lupa bahwa salinan mengganti nama file untuk menggunakan garis bawah
Fernando Castilla Ospina
9

Saya melihat semua jawaban dan ada pilihan lain yang tersisa. Anda dapat mengubah nilai CMD Anda dalam file buruh pelabuhan (ini bukan yang terbaik, tapi masih mungkin cara untuk mencapai tujuan Anda).

Pada dasarnya kita perlu

  • Salin file konfigurasi di penampung buruh pelabuhan
  • Ganti opsi mulai postgres

Contoh file Docker:

FROM postgres:9.6
USER postgres

# Copy postgres config file into container
COPY postgresql.conf /etc/postgresql

# Override default postgres config file
CMD ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"]

Meskipun saya pikir menggunakan file command: postgres -c config_file=/etc/postgresql/postgresql.confAnda yang docker-compose.ymldiusulkan oleh Matthias Braun adalah pilihan terbaik.

Dr Botwing
sumber
2

Solusi berteknologi rendah untuk masalah ini tampaknya menyatakan layanan (saya menggunakan swarm di AWS dan file yaml) dengan file database Anda dipasang ke volume yang tetap (di sini AWS EFS sebagaimana dilambangkan oleh cloudstor: aws driver spesifikasi).

  version: '3.3'
  services:
    database:
      image: postgres:latest
      volumes:
        - postgresql:/var/lib/postgresql
        - postgresql_data:/var/lib/postgresql/data
    volumes:
       postgresql:
         driver: "cloudstor:aws" 
       postgresql_data:
         driver: "cloudstor:aws"
  1. DB muncul seperti yang diinisialisasi dengan pengaturan default gambar.
  2. Anda mengedit pengaturan conf di dalam penampung, misalnya jika Anda ingin meningkatkan jumlah maksimum koneksi bersamaan yang membutuhkan restart
  3. hentikan container yang sedang berjalan (atau turunkan skala layanan ke nol lalu kembali ke satu)
  4. gerombolan itu memunculkan penampung baru, yang kali ini mengambil setelan konfigurasi Anda yang sudah ada dan menerapkannya dengan riang.

Efek samping yang menyenangkan dari mempertahankan konfigurasi Anda adalah bahwa itu juga mempertahankan database Anda (atau sebaliknya) ;-)

Eoan
sumber
2

Solusi saya adalah untuk kolega yang perlu membuat perubahan dalam konfigurasi sebelum meluncurkan docker-entrypoint-initdb.d

Saya perlu mengubah pengaturan 'shared_preload_libraries' sehingga selama bekerja, postgres sudah memiliki perpustakaan baru yang dimuat sebelumnya dan kode di docker-entrypoint-initdb.d dapat menggunakannya.

Jadi saya baru saja menambal file postgresql.conf.sample di Dockerfile:

RUN echo "shared_preload_libraries='citus,pg_cron'" >> /usr/share/postgresql/postgresql.conf.sample
RUN echo "cron.database_name='newbie'" >> /usr/share/postgresql/postgresql.conf.sample

Dan dengan tambalan ini memungkinkan untuk menambahkan ekstensi dalam file .sql di docker-entrypoint-initdb.d /:

CREATE EXTENSION pg_cron;
40 menit
sumber
1

Ini bekerja untuk saya:

FROM postgres:9.6
USER postgres

# Copy postgres config file into container
COPY postgresql.conf /etc/postgresql

# Override default postgres config file
CMD ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"]
Guillermo Solis
sumber
Mengapa ini tidak menerima suara positif apa pun? Ini adalah proposisi yang paling waras di sini ... Terima Kasih.
Paflow
0

Menggunakan buruh pelabuhan menulis Anda dapat memasang volume dengan postgresql.auto.conf. Contoh:

version: '2'

services:
  db:
    image: postgres:10.9-alpine
    volumes:
      - postgres:/var/lib/postgresql/data:z
      - ./docker/postgres/postgresql.auto.conf:/var/lib/postgresql/data/postgresql.auto.conf
    ports:
      - 5432:5432
Botak
sumber
Anda tidak boleh mengedit postgresql.auto.confkarena sudah ditimpa. Gunakan postgresql.confdi lokasi yang sama.
Baschdl
0

Saya juga menggunakan gambar resmi ( FROM postgres) dan saya dapat mengubah konfigurasi dengan menjalankan perintah berikut.

Hal pertama adalah mencari file konfigurasi PostgreSQL. Ini dapat dilakukan dengan menjalankan perintah ini di database Anda yang sedang berjalan.

SHOW config_file;

Saya kasus saya itu kembali /data/postgres/postgresql.conf.

Langkah selanjutnya adalah mencari tahu apa hash dari container docker PostgreSQL Anda yang sedang berjalan.

docker ps -a

Ini harus mengembalikan daftar semua kontainer yang berjalan. Dalam kasus saya, tampilannya seperti ini.

...
0ba35e5427d9    postgres    "docker-entrypoint.s…" ....
...

Sekarang Anda harus beralih ke bash di dalam penampung Anda dengan menjalankan:

docker exec -it 0ba35e5427d9 /bin/bash

Di dalam wadah, periksa apakah konfigurasi berada di jalur yang benar dan tampilkan.

cat /data/postgres/postgresql.conf

Saya ingin mengubah koneksi maks dari 100 menjadi 1000 dan buffer bersama dari 128MB menjadi 3GB. Dengan perintah sed saya dapat melakukan pencarian dan mengganti dengan variabel yang sesuai di konfigurasi.

sed -i -e"s/^max_connections = 100.*$/max_connections = 1000/" /data/postgres/postgresql.conf
sed -i -e"s/^shared_buffers = 128MB.*$/shared_buffers = 3GB/" /data/postgres/postgresql.conf

Hal terakhir yang harus kita lakukan adalah memulai ulang database di dalam container. Cari tahu versi PostGres mana yang Anda gunakan.

cd /usr/lib/postgresql/
ls 

Dalam kasus saya ini 12 Jadi Anda sekarang dapat memulai ulang database dengan menjalankan perintah berikut dengan versi yang benar di tempat.

su - postgres -c "PGDATA=$PGDATA /usr/lib/postgresql/12/bin/pg_ctl -w restart"
Sebastian
sumber