[컴] docker centos 8 에서 /run/nologin

centos nologin /

docker centos 8 에서 /run/nologin

centos 8(centos:centos8) 으로 만든 docker container 에서 ssh-copy-id 를 하려고 login을 시도하니 아래처럼 error 가 나왔다.

docker container 에는 rsync 라는 user 가 추가되어 있다.

[rsync@fd66a850ce00 ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub node1
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/rsync/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
rsync@node1's password:
"System is booting up. Unprivileged users are not permitted to log in yet. Please come back later. For technical details, see pam_nologin(8)."
Connection closed by 172.19.0.2 port 22

root 을 제외한 ssh login 자체가 안됐다.

sh-4.4# ssh rsync@node1
rsync@node1's password:
"System is booting up. Unprivileged users are not permitted to log in yet. Please come back later. For technical details, see pam_nologin(8)."
Connection closed by 172.19.0.2 port 22

/run/nologin 삭제

pam_nologin(8) - Linux man page 에는 /etc/nologin 이라고 되어 있는데, docker container 에서는 /etc/nologin 은 없고, /run/nologin 에 존재했다.

이 파일을 삭제하면 잘 동작한다.

sh-4.4# ls /run/nologin -al
-rw-r--r-- 1 root root 142 Sep 15 14:17 /run/nologin
sh-4.4# rm /run/nologin

Dockerfile에 넣으면 된다.

RUN rm -rf /run/nologin

/run/nologin

2016년 글에는 /run/nolgin 은 systemd 와 관련있고, 원래는 /tmpfs 에 생성되는 것이라 한다. 이것이 container 에는 필요없을 것이라고, 이것을 삭제했다고 나와있다.

그런데 2018년에는 다시 생긴 듯 하다.

여하튼 2016년 기준으로는 지워도 무방하다고 이야기 한다.

References

[컴] 파일동기화, login 없이 rsync 사용하기

 

synchronize / file synch / without login

파일동기화, login 없이 rsync 사용하기

  • rsync_test.zip
  • compose.yml
  • entorypoint.sh : 단지, sshd 서버를 띄우기 위함.
#
# compose.yml
#
version: '3.8'

services:
  node1:
    container_name: node1
    build: .
    image: alpine:3.14-rsync
    volumes:
      - ./data1:/data_sync
    networks:
      - rsync-network
    ports:
      - "7795:22"
    restart: always
    entrypoint: [ "/entrypoint.sh" ]
  node2:
    container_name: node2
    build: .
    image: alpine:3.14-rsync
    volumes:
      - ./data2:/data_sync
    networks:
      - rsync-network
    ports:
      - "7796:22"
    restart: always
    entrypoint: [ "/entrypoint.sh" ]
  node3:
    container_name: node3
    build: .
    image: alpine:3.14-rsync
    volumes:
      - ./data3:/data_sync
    networks:
      - rsync-network
    ports:
      - "7797:22"
    restart: always
    entrypoint: [ "/entrypoint.sh" ]
networks:
  rsync-network:
    driver: bridge
#
# Dockerfile
#
FROM alpine:3.14


RUN apk add rsync
RUN apk add --update --no-cache openssh

RUN addgroup -g 1000 rsync
RUN adduser -D -G rsync rsync
# in centos
# RUN groupadd -g 1000 rsync
# RUN adduser -g rsync rsync
RUN echo -n 'rsync:my_password' | chpasswd

COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh 
#!/bin/sh
#
# entrypoint.sh
#
ssh-keygen -A
exec /usr/sbin/sshd -D -e "$@"

login 을 안해도 되도록 만들기

여기서 rsync 를 하려는 remote 의 주소를 112.123.23.0 라고 하자.

  • 먼저 rsync 로 접근하려는 remote 에 가서 계정을 만들고 비번을 걸어놓자.
  • local 에서 작업
    • ssh-keygen : password 넣으라고 나오면 그냥 enter 를 친다.
    • ssh-copy-id -i ~/.ssh/id_rsa.pub 112.123.23.0 : 112.123.23.0 에 public key 를 copy 해 준다. 이때 내 현재 계정이 rsync 라면 rsync 로 112.123.23.0에 접속하게 된다. 이 때 비밀번호를 물어보게 된다. 인증이 잘되면, pub key 가 옮겨진다.
    • ssh 112.123.23.0 를 하면 접근이 되는 것을 알 수 있다.
    • 참고로, 다른 계정에서 rsync@112.123.23.0 -i /home/rsync/.ssh/id_rsa 으로 하면 그냥 접근이 된다. 그래서 id_rsa 의 권한은 항상 600으로 하자.(기본으로 되어 있다.)
  • rsync -rv rsync@node1:/data_sync / : node1의 data_sync 폴더 전부를 local 의 ‘/’ 로 옮겨준다. 그래서 ’/’에 data_sync 가 생긴다.
# su - rsync
# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
...
# ssh-copy-id -i ~/.ssh/id_rsa.pub node1
...
# rsync -rv rsync@node1:/data_sync /

See Also

  1. 쿠…sal: [컴] rsync 정리
  2. 쿠...sal: [컴] docker centos 8 에서 /run/nologin : centos image로 테스트하면 login 이 안되는 이슈가 있을 수 있다. 그것과 관련된 내용이다.

Reference

  1. How To Use Rsync Without Password

[컴] rsync 정리

 

동기 /

rsync 정리

rsync options

자세한 옵션은 ref. 3 에서 확인

  • –a: archive mode
  • –v: shows details of the copying process
  • –p: shows the progress bar
  • –r: copies data recursively
  • –z: compresses data
  • –q: suppress output
  • -h: human readable

remote 에 있는 file 들을 동기화 할 때

remotely, you will require:

  1. local 과 remote system 모두에 rsync 가 설치돼야 한다.
  2. remote system 에 대해 SSH access 가 돼야 한다.
  3. Remote user password

rsync 사용 예시

rsync -avh source/ dest/ --delete
rsync -a --exclude="*.zip" /home/tin/Downloads/ /home/tin/Documents
rsync -v ~/Downloads/file1.txt umara@192.168.72.164:~/Documents
rsync -rv umara@192.168.72.164:~/Downloads/sample ~/Desktop/test

See Also

  1. 쿠…sal: [컴] 파일동기화 login 없이 rsync 하기

References

  1. How to use rsync to copy files
  2. backup - How do I make rsync delete files that have been deleted from the source folder? - Ask Ubuntu
  3. rsync(1) - Linux man page

[컴] nginx 에서 1mb 가 넘는 file 을 받지 않는 경우

client_max_body_size / 서버 1mb 제한 / 큰 파일 못받는 이유

nginx 에서 1mb 가 넘는 file 을 받지 않는 경우.

nginx 에서 client_max_body_size directive 로 client request body 의 최대 size 를 정할 수 있다. 기본값은 1MiB 이다.(ref. 2 참고) size 가 정해놓은 값을 넘기면 413 error 를 client 에게 주게 된다.

http{
    ...
    client_max_body_size 100m;
    ...
}

nginx의 error log 에서 아래같은 메시지를 볼 수 있다.

[error] 25556#0: *52 client intended to send too large body:

매우 큰 사이즈 파일들은 client_body_timeout 값도 변경하는 것이 좋다. 기본값은 60초 이다.[ref. 1, 3]

References

  1. Increasing file upload size limit in nginx - Scale Dynamix
  2. Default nginx client_max_body_size - Stack Overflow
  3. Module ngx_http_core_module

[컴][db] mongodb replica set 설정 절차

몽고db 레플리카 / backup /구성

mongodb replica set 설정 절차

  1. replica set 의 각 member 들을 실행
  2. 이중 한 mongod instance 에 mongosh(command 는 mongo 이다.) 를 실행한다. 이때 1번째 node 주소를 넣어서 접속하자. mongo --host mongo1:27017
  3. 그리고 shell 에서 rs.initiate() 를 실행한다.(아래 참고)
  4. rs.conf() 를 하면 설정된 내역이 보인다. 이 내용이 mongodb data 에 저장된 내용이기에, 한번 rs.initiate 를 하고나면, 다음에 mongodb 를 restart 를 해도 다시 rs.initiate 를 해줄 필요는 없다.(참고:Replica Set Configuration — MongoDB Manual)
  5. rs.status() 를 하면 누가 primary 인지 확인할 수 있다. rs.initiate() 가 된 이후에 mongod 를 restart 하면 자동으로 알아서 replicaset 을 구성하는데, 최초에 primary 를 정하기 위해 election 을 한다. 그래서 뜨자마자 rs.status() 를 때리는 경우에 모두가 SECONDARY 로 있다가 election 에 의해 PRIMARY 가 정해진다.(추측)
    rs.initiate( {
       _id : "rs0",
       members: [
          { _id: 0, host: "mongodb0.example.net:27017" },
          { _id: 1, host: "mongodb1.example.net:27017" },
          { _id: 2, host: "mongodb2.example.net:27017" }
       ]
    })

/* rs.status() */
{
    "set" : "dbrs",
    ...
    "members" : [ 
        {
            "_id" : 0,
            "name" : "mongo1:27017",
            "health" : 1.0,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 1070,
            "optime" : {
                "ts" : Timestamp(1642120547, 1),
                "t" : NumberLong(2)
            },
            "optimeDate" : ISODate("2022-01-14T00:35:47.000Z"),
            "lastAppliedWallTime" : ISODate("2022-01-14T00:35:47.494Z"),
            "lastDurableWallTime" : ISODate("2022-01-14T00:35:47.494Z"),
            "syncSourceHost" : "",
            "syncSourceId" : -1,
            "infoMessage" : "",
            "electionTime" : Timestamp(1642119527, 1),
            "electionDate" : ISODate("2022-01-14T00:18:47.000Z"),
            "configVersion" : 1,
            "configTerm" : 2,
            "self" : true,
            "lastHeartbeatMessage" : ""
        }, 
        {
            "_id" : 1,
            "name" : "mongo2:27017",
            "health" : 1.0,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 1032,
            "optime" : {
                "ts" : Timestamp(1642120547, 1),
                "t" : NumberLong(2)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1642120547, 1),
                "t" : NumberLong(2)
            },
            "optimeDate" : ISODate("2022-01-14T00:35:47.000Z"),
            "optimeDurableDate" : ISODate("2022-01-14T00:35:47.000Z"),
            "lastAppliedWallTime" : ISODate("2022-01-14T00:35:47.494Z"),
            "lastDurableWallTime" : ISODate("2022-01-14T00:35:47.494Z"),
            "lastHeartbeat" : ISODate("2022-01-14T00:35:48.162Z"),
            "lastHeartbeatRecv" : ISODate("2022-01-14T00:35:47.266Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncSourceHost" : "mongo1:27017",
            "syncSourceId" : 0,
            "infoMessage" : "",
            "configVersion" : 1,
            "configTerm" : 2
        }, 
        {
            "_id" : 2,
            "name" : "mongo3:27017",
            "health" : 1.0,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 1032,
            "optime" : {
                "ts" : Timestamp(1642120547, 1),
                "t" : NumberLong(2)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1642120547, 1),
                "t" : NumberLong(2)
            },
            "optimeDate" : ISODate("2022-01-14T00:35:47.000Z"),
            "optimeDurableDate" : ISODate("2022-01-14T00:35:47.000Z"),
            "lastAppliedWallTime" : ISODate("2022-01-14T00:35:47.494Z"),
            "lastDurableWallTime" : ISODate("2022-01-14T00:35:47.494Z"),
            "lastHeartbeat" : ISODate("2022-01-14T00:35:48.163Z"),
            "lastHeartbeatRecv" : ISODate("2022-01-14T00:35:47.265Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncSourceHost" : "mongo1:27017",
            "syncSourceId" : 0,
            "infoMessage" : "",
            "configVersion" : 1,
            "configTerm" : 2
        }
    ],
    ...
}

priority 조정 방법

priority 가 조정되면, 조정된 값은 mongodb 가 꺼졌다가 켜져도 유지된다.

cfg = rs.conf()
cfg.members[0].priority = 2
rs.reconfig(cfg)

auth 를 사용하면 key 가 필요하다.

3개의 node 가 있다면, 3개가 다 같은 key file 을 사용해야 한다.

키파일 생성은 아래처럼 하면 된다.

$ openssl rand -base64 756 > /var/lib/mongo/replica_set_key
$ chmod 400 /var/lib/mongo/replica_set_key

그리고 이 key file 의 path 를 지정해 주면 된다.

parameter 로 직접 넘길 수도 있고,

mongod --auth --keyFile /var/lib/mongo/replica_set_key --port 27017 --dbpath /var/lib/mongodb

또는 configuration file 에 설정을 해줄 수도 있다.

# mongod.conf

...
#processManagement:

security:
  authorization: enabled
  keyFile: /var/lib/mongo/replica_set_key
...

replicaSet의 port 변경시

기존의 replicaSet 의 port 를 변경하는 경우이다. 예를 들어 현재 27017 로 replica set 이 구성되어 있는 mongodb 를 port 27018로 replicaSet을 구성하는 경우

  1. 먼저 모든 mongod 를 다 내리자.

  2. 그리고 모든 node의 monogd port 를 변경

  3. primary node 를 띄우자.

  4. 기존의 rs 정보를 삭제 [ref. 3]

    use local
    db.system.replset.find()
    db.system.repset.remove({"_id": "rs0"})
    db.system.replset.find()
  5. primary node 외의 node 에서 dbPath 의 data 를 모두 지우고, 모든 node 를 전부 띄운다(run).

    dbPath 를 안지우고, 다른 secondary node를 띄우면, node의 replica set ID 가 맞지 않는다는 error 가 나온다.

    ...
    "errmsg" : "Our replica set ID of xxxxx did not match that of 13.76.170.50:27017, which is xxxxxx",
    ...

    그래서 primary 노드 외에 다른 node의 dbPath(mongod.conf에 설정된) 의 데이터를 지운다. dbPath 의 owner 설정에 주의해야 할 수 있다.

    mv /myapps/mongo/data/ /myapps/mongo/data_20220418
    mkdir /myapps/mongo/data && chowner mongod:mongod /myapps/mongo/data/

    그리고 실행을 하면, secondary node 로 data 가 다시 복사된다. 그리고 cluster 연결이 잘된다.

  6. rs.initiate() 을 다시 한다.

    rs.initiate( {
        _id : "rs0",
        members: [
          { _id: 0, host: "cluster1.mylocal.com:27018" },
          { _id: 1, host: "cluster2.mylocal.com:27018" },
          { _id: 2, host: "cluster3.mylocal.com:27018" }
        ]
    })
  7. cluster 연결이 되고 나서, primary node 로 사용했던 1번째 node의 status 가 RECOVERING상태에서 돌아오지 않아서, 1번째 node의 mongod 를 stop 하고, dbPath 를 지운후에 다시 띄웠다.

    • primary node 에서 rs.status() 를 확인하면 "Could not find member to sync from" 이란 message가 보인다. 그래서 rs.syncFrom 를 했는데, 변화가 없었다. 그래서 그냥 dbPath 를 지웠다.

See Also

  1. 쿠…sal: [컴][db] mongodb 를 production 에서 배포시 확인할 사항
  2. Change Hostnames in a Replica Set — MongoDB Manual
  3. 쿠...sal: [컴][db] mongodb, replica set 

Reference

  1. Deploy a Replica Set — MongoDB Manual
  2. MongoDB keyfile | How Keyfile works in MongoDB?
  3. How to reset MongoDB replica set settings - Server Fault
  4. replicaset - mongodb : could not find member to sync from - Stack Overflow

[컴] docker 에서 /etc/hosts 변경

 

docker에서 >> 가 동작하지 않는다 / hosts 변경 방법

docker 에서 /etc/hosts 변경

Dockerfile 에서 아래처럼 >> 를 사용해봤다.

# Dockerfile
...
RUN cat /tmp/hosts >> /etc/hosts
...

아래처럼 error 가 발생했다.

 > [7/7] RUN cat /tmp/hosts >> /etc/hosts:
#11 0.321 /bin/sh: /etc/hosts: Read-only file system
------
failed to solve: rpc error: code = Unknown desc = executor failed running [/bin/sh -c cat /tmp/hosts >> /etc/hosts]: exit code: 1

ref. 1 에 보면 이유를 알 수 있는데, Docker 가 /etc/hosts file 을 container 가 시작할 때 생성한다고 한다. 그래서 CMD 를 이용해서 container 에서 실행하도록 해야 한다.

CMD cat /tmp/hosts >> /etc/hosts

하지만 이것도 build 시점에 error 를 보여주진 않지만, 원하는대로 동작하지 않는다.

/etc/hosts 를 변경하지 말고, extra_hosts 를 사용하자.

ref. 2 에 보면, build 시점에 /etc/hosts 를 하지말라고 한다. container 가 실행되는 시점에 바꿔야 한다고 한다.

그래서 2가지 방법을 알려준다.

  1. docker run –add-host=
  2. docker compose 의 extra_hosts directive
# compose.yml

extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

References

  1. docker - Modify hosts file in dockerfile - Server Fault
  2. dockerfile - How to update /etc/hosts file in Docker image during “docker build” - Stack Overflow

[컴][db] 몽고db 설치시 다른 directory 사용방법

 mongodb install

몽고db 설치시 다른 directory 사용방법


기본 directory

따로 설정하지 않으면 기본 path 는 아래와 같다.

  • /var/lib/mongo (the data directory)
  • /var/log/mongodb (the log directory)

다른 directory 사용법

/etc/mongod.conf에서 설정한다.

  • storaage.dbPath
  • systemLog.path

값을 변경해주면 된다.

그리고 mongodb 를 실행하는 user가 directory 가 접근가능하게 해준다. 만약 mongod 가 mongodb 를 실행한다고 하면 다음처럼 하면 된다.

sudo chown -R mongod:mongod <directory>

아래처럼 option 으로도 db path 를 변경할 수 있다.

mongod --bind_ip localhost --port 27017 --dbpath /new/mongodb/db/